package com.android.scj.tc;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.Constant;
import com.android.scj.tc.bean.EerrBean;
import com.baseutils.SpfUtils;
import com.util.HexUtil;

import java.util.logging.Handler;


public class TcAppFolw {
    public static String DATATrada = "00";
    private static CMD_Manager manager = null;
    private String strResult = null;
    private static String strVst = null;
    private static String strGetSecure = null;
    private static String strGetRand = null;
    private static String strTransferChannel = null;
    private static String strTransferChannelPrivate = null;
    private static String strSetMMi = null;
    private static String strGetTollData = null;
    private static String strSetTollData = null;
    private static String strPsamRst = null;
    private static String strPsamCmd = null;
    private static String strGetSecureRand = null;
    private static int nLenVehiInfo = 0;

    private static String strMacId = null;
    private static String strLLC = "77";

    private static int nCardNoExist = 0;//卡片是否存在
    private static int nCardIsGx = 0;//卡片地区广西
    private static int nCardAlgId = 0;//卡片算法标识，0表示DES，4表示国密
    private static int nObuAlgId = 0;//OBU算法标识，0表示DES，4表示国密
    public static int nCardVersionType = 0;// ０表示旧版卡，１表示４X版本卡
    public static int nObuVersionType = 0;// OBU版本，0表示旧版本，1表示4X版本
    private static String strVst0015 = "";
    private static String strVst0002 = "";
    private static String strVstSystemFile = "";
    private static String strVstObuStatus = "";
    private static String strVstRandom = "";
    private static String strEsamSystemFile2 = "";// 系统信息27字节后面的信息
    private static String str0002 = "";//通过TransferChannel
    private static String str0019 = "";//通过TransferChannel
    private static String str0015 = "";//通过TransferChannel
    private static String str001B = "";//通过TransferChannel
    private static String strEsamVehicleFile = "";//车辆信息明文
    private static String strGetTollInfo = "";//过站信息
    private static String strTacInfo = "";//TAC信息
    private static String strAuthenticator = "";//鉴别码
    private static int nIsObuOneChip = 0;//1表示单片式
    private static String strExminObuMac = "";
    private static int nIsCheckEsamIccVersion = 0;//核对OBU和卡片版本，1表示核对，0表示不核对


    private static String strApduList = null;
    // private static String[] strApduList = new

    public static String getPsamSoltSignChip() {
        return psamSoltSignChip;
    }

    public static void setPsamSoltSignChip(String psamSoltSignChip) {
        TcAppFolw.psamSoltSignChip = psamSoltSignChip;
    }

    public static String psamSoltSignChip = "02";

    public static String psamSolt = "02";
    public static String psamSoltWrite = "02";

    public static String DecryptKeyType = "59";
    public static String WriteKeyType = "26";
    public static String WriteKeyId = "01";
    public static String WritePsamDir = "DF02";
    public static String AreaName = "聚利";


    public static String PsamIdNumber = "000000000000";

    private static final byte MAC_CONTROL = 4;

    private static final byte ACTION_RQ = MAC_CONTROL + 3;
    private static final byte ACTION_RS = MAC_CONTROL + 4;

    private static final byte ACTION_TYPE = ACTION_RQ + 2;

    private static final byte DOWN_CONTAINER = ACTION_TYPE + 1;
    private static final byte UP_CONTAINER = ACTION_RS + 2;

    private static final byte DOWN_CONTAINER_G = ACTION_TYPE + 8;
    /******* DSRC_LINK ********************/
    private static final byte LINK_UP = (byte) 0x80;
    private static final byte LINK_DOWN = (byte) 0x40;
    /********* DSRC ACTION REQUEST/RESPONSE ****************************/
    private static final byte TYPE_BST = (byte) 0xC0;
    private static final byte TYPE_VST = (byte) 0xD0;
    private static final byte TYPE_EVENT = (byte) 0x60;

    private static final byte TYPE_ACTION_RQ = (byte) 0x05;
    private static final byte TYPE_ACTION_RQ1 = (byte) 0x00;
    private static final byte TYPE_ACTION_RS = (byte) 0x18;
    private static final byte TYPE_ACTION_RS1 = (byte) 0x10;
    /******** CONTAINER EVENT_REPORT ************************************/
    private static final byte C_GET_RQ = (byte) 0x14;
    private static final byte C_GET_RS = (byte) 0x15;
    private static final byte C_TRAN_RQ = (byte) 0x18;
    private static final byte C_TRAN_RS = (byte) 0x19;
    private static final byte C_SETM_RQ = (byte) 0x1A;
    private static final byte C_SETM_RS = (byte) 0x1B;
    private static final byte C_GETRNAD_RS = (byte) 0x1D;
    private static final byte C_GETTOLLDATA_RQ = (byte) 0x2A;
    private static final byte C_GETTOLLDATA_RS = (byte) 0x2B;
    private static final byte C_SETTOLLDATA_RQ = (byte) 0x2C;
    private static final byte C_SETTOLLDATA_RS = (byte) 0x2D;

    private static final byte R_BST = (byte) 0x01;
    private static final byte R_VST = (byte) 0x02;
    private static final byte R_GET_RQ = (byte) 0x03;
    private static final byte R_GET_RS = (byte) 0x04;
    private static final byte R_TRANS_RQ = (byte) 0x05;
    private static final byte R_TRANS_RS = (byte) 0x06;
    private static final byte R_SETM_RQ = (byte) 0x07;
    private static final byte R_SETM_RS = (byte) 0x08;
    private static final byte R_EVENT_REPORT = (byte) 0x09;
    private static final byte R_GETRAND_RS = (byte) 0x0A;
    private static final byte R_GETTOLLDATA_RQ = (byte) 0x0B;
    private static final byte R_GETTOLLDATA_RS = (byte) 0x0C;
    private static final byte R_SETTOLLDATA_RQ = (byte) 0x0D;
    private static final byte R_SETTOLLDATA_RS = (byte) 0x0E;

    private static final byte VST_OPTION_ETC = (byte) 0x01;
    private static final byte VST_OPTION_DID = (byte) 0x80;
    private static final byte VST_RESOLVE_START = (byte) 0x09;
    private static final byte VST_RESOLVE_START_OLD = (byte) 10;
    private static final byte CONTAINER_MF1_LEN = 52;
    private static final byte CONTAINER_RAND = 29; // Rand

    private static final byte CONTAINER_RAND_LEN = 8; // Random Length

    /*************** return ****************/
    private static final byte ERROR_NO_ETC_A = 19; //
    private static final byte ERROR_NOSYSFILE = 20; //
    private static final byte ERROR_LEN_ERROR = 21; //
    private static final byte ERROR_VST_L_MAC = 22; //
    private static final byte EFFOR_MF1 = 23; //
    private static final byte ERROR_VST_RAND = 40;
    private static final byte ERROR_CHANNEL_SW = 37;
    private static final byte ERROR_SW = 38;

    private static final byte LEN_SYS = 26;
    private static final byte VST_15_LEN = 43;

    public static int AREA = -1;
    public static final int AREA_ITS = 0;// 聚利
    public static final int AREA_SX = 1;// 陕西
    public static final int AREA_AH = 2; // 安徽
    public static final int AREA_SC = 3; // 江苏四川
    public static final int AREA_ZJ = 4; // 浙江
    public static final int AREA_GZ = 5; // 贵州
    public static final int AREA_SD = 6; // 山东
    public static final int AREA_HB = 7; // 河北
    public static final int AREA_YN = 8; // 云南
    public static final int AREA_FJ = 9; // 福建
    public static final int AREA_LL = 10; // 辽宁
    public static final int JUNCHE = 11;// 军车
    public static final int AREA_TJ = 12;// 天津
    public static final int AREA_HN = 13;// 湖南
    public static final int AREA_ZH = 14;// 总后
    public static final int AREA_SX2 = 15;// 山西

    /**
     *
     */
//	public   int SOFT=0;
    Context context;
    Boolean aBoolean;

    //	1 软算法  ０ psam
    public TcAppFolw(Context context, Boolean aBoolean) {
        this.context = context;
        this.aBoolean = aBoolean;
        if (aBoolean) {
            SOFT = 0;
        } else {
            SOFT = 1;
        }
        manager = CMD_Manager.getCMDManager(context);
        String Areas = (String) SpfUtils.get(context, Constant.Area, "聚利");
        UpdateArea(Areas);
    }

    /**
     * 获取地区代码
     *
     * @param area
     * @return
     */
    public static int getAreaCode(String area) {
        if ("聚利".equals(area))
            return AREA_ITS;
        else if ("陕西".equals(area))
            return AREA_SX;
        else if ("安徽".equals(area))
            return AREA_AH;
        else if ("江苏".equals(area))
            return AREA_SC;
        else if ("浙江".equals(area))
            return AREA_ZJ;
        else if ("贵州".equals(area))
            return AREA_GZ;
        else if ("山东".equals(area))
            return AREA_SD;
        else if ("河北".equals(area))
            return AREA_HB;
        else if ("云南".equals(area))
            return AREA_YN;
        else if ("福建".equals(area))
            return AREA_FJ;
        else if ("辽宁".equals(area))
            return AREA_LL;
        else if ("军车".equals(area))
            return JUNCHE;
        else if ("天津".equals(area))
            return AREA_TJ;
        else if ("湖南".equals(area))
            return AREA_HN;
        else if ("总后".equals(area))
            return AREA_ZH;
        else if ("山西".equals(area))
            return AREA_SX2;
        else
            return AREA_ITS;
    }

    /**
     * 解析DSRC数据类型
     *
     * @param
     * @return
     */
    private byte ResolveDsrcAction(byte[] pData) {
        byte xReturn = 0;

        if ((pData[MAC_CONTROL] & LINK_UP) == LINK_UP) {// 上行
            if ((pData[ACTION_RQ] == TYPE_VST) || (pData[ACTION_RQ + 1] == TYPE_VST)) {
                xReturn = R_VST;
            } else if ((pData[ACTION_RS] & TYPE_ACTION_RS1) == TYPE_ACTION_RS1) {
                switch (pData[UP_CONTAINER]) {
                    case C_GET_RS:
                        xReturn = R_GET_RS;
                        break;
                    case C_TRAN_RS:
                        xReturn = R_TRANS_RS;
                        break;
                    case C_SETM_RS:
                        xReturn = R_SETM_RS;
                        break;
                    case C_GETRNAD_RS:
                        xReturn = R_GETRAND_RS;
                        break;
                    case C_GETTOLLDATA_RS:
                        xReturn = R_GETTOLLDATA_RS;
                        break;
                    case C_SETTOLLDATA_RS:
                        xReturn = R_SETTOLLDATA_RS;
                        break;
                }
            }
        } else if ((pData[MAC_CONTROL] & LINK_DOWN) == LINK_DOWN) {// 下行
            if (pData[ACTION_RQ] == TYPE_BST) {
                xReturn = R_BST;
            } else if (pData[ACTION_RQ] == TYPE_EVENT) {
                xReturn = R_EVENT_REPORT;
            } else if (pData[ACTION_RQ] == TYPE_ACTION_RQ) {
                switch (pData[DOWN_CONTAINER]) {
                    case C_GET_RQ:
                        xReturn = R_GET_RQ;
                        break;
                    case C_TRAN_RQ:
                        xReturn = R_TRANS_RQ;
                        break;
                    case C_SETM_RQ:
                        xReturn = R_SETM_RQ;
                        break;
                }
            }
        } else
            xReturn = 0;
        return xReturn;

    }

    private static byte VstResolve(byte[] pVst, byte len) throws Exception {
        byte offset = 9;
        byte flag;
        nCardVersionType = 0;
        nObuVersionType = 0;
        strVst0015 = "";
        strVst0002 = "";
        offset++;
        // byte[] pVst = new byte[pData.length];
        // System.arraycopy(pData,9,pVst,0,pData.length-9);
        // len -=9;

        if ((pVst[offset] & 0x3F) != VST_OPTION_ETC)
            return ERROR_NO_ETC_A;
        if ((pVst[offset] & VST_OPTION_DID) == VST_OPTION_DID)
            offset++;// DID
        offset++;

        flag = pVst[offset];// ApplicationContextMark
        offset++;

        if ((flag & 0x20) == 0x20) {
            if ((pVst[offset] != 0x27) && (pVst[offset] != 0x20))//
                return ERROR_NOSYSFILE;
        }
        offset++;

        strVstSystemFile = strVst.substring(offset * 2, offset * 2 + LEN_SYS
                * 2);


        int nObuVersion = Integer.parseInt(strVstSystemFile.substring(9 * 2, 10 * 2), 16);
        if ((nObuVersion & 0x40) == 0x40)
            nObuVersionType = 1;
        else
            nObuVersionType = 0;
        if ((nObuVersion & 0x50) == 0x50)
            nObuAlgId = 4;
        else
            nObuAlgId = 0;

        strVstRandom = "";
        offset += LEN_SYS;
        if ((flag & 0x80) == 0x80) {
            if (pVst[offset] != CONTAINER_RAND)
                return ERROR_VST_RAND;
            strVstRandom = strVst.substring((offset + 1) * 2, (offset + 1) * 2
                    + CONTAINER_RAND_LEN * 2);
            offset += (CONTAINER_RAND_LEN + 1);
        }

        if (offset > len)
            return ERROR_LEN_ERROR;
        strVstObuStatus = strVst.substring((len - 3) * 2, (len - 3) * 2 + 6);
        Log.e("test", "len" + len + ",obu status=" + strVstObuStatus);
        int nObuStatus = Integer.parseInt(strVstObuStatus.substring(2, 4), 16);
        if ((nObuStatus & 0x80) == 0x80)
            nCardNoExist = 1;
        else
            nCardNoExist = 0;

        nIsObuOneChip = Integer.parseInt(strVstObuStatus.substring(0, 2), 16);
        if ((nIsObuOneChip & 0xF0) == 0x40)
            nIsObuOneChip = 1;
        else
            nIsObuOneChip = 0;
        if (nIsObuOneChip == 1) return 0;
        if ((flag & 0x40) != 0x40) {// 判断是否存在预读
            if (pVst[offset] == 40) {
                offset++;
                strVst0015 = strVst.substring(offset * 2, offset * 2
                        + VST_15_LEN * 2);
                int nCardVersion = Integer.parseInt(strVst0015.substring(9 * 2, 10 * 2), 16);
                if ((nCardVersion & 0x40) == 0x40)
                    nCardVersionType = 1;
                else
                    nCardVersionType = 0;
                if ((nCardVersion & 0x50) == 0x50)
                    nCardAlgId = 4;
                else
                    nCardAlgId = 0;
                if (strVst0015.substring(0, 8).equals("B9E3CEF7"))
                    nCardIsGx = 1;
                else
                    nCardIsGx = 0;
                offset += VST_15_LEN;
                strVst0002 = strVst.substring(offset * 2, offset * 2 + 4 * 2);
            } else {
                strVst0015 = "";
                strVst0002 = "";
            }

        }

        return 0;
    }

    /*
     * 1表示不存在，0表示存在
	 */
    public int GetCardExistStatus() {
        return nCardNoExist;
    }

    public String GetVehicleInfo() {
        return strEsamVehicleFile;
    }

    public String GetCardIssuer() throws Exception {
        // Log.i("test","strVst0015="+strVst0015);
        if (strVst0015.equals(""))
            return "";
        return HexUtil.HexToAsciiString(strVst0015.substring(0, 8 * 2));
    }

    public String GetCardType() {
        if (strVst0015.equals(""))
            return "";
        return GetCardType(strVst0015.substring(8 * 2, 9 * 2));
    }

    public String GetCardVersion() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(9 * 2, 10 * 2);
    }

    public String GetCardNetNumber() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(10 * 2, 12 * 2);
    }

    public String GetCardSerialNumber() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(12 * 2, 20 * 2);
    }

    public String GetCardDate1() {
        if (strVst0015.equals(""))
            return "";
        return convertDate(strVst0015.substring(20 * 2, 20 * 2 + 8));
    }

    public String GetCardDate2() {
        if (strVst0015.equals(""))
            return "";
        return convertDate(strVst0015.substring(20 * 2 + 8, 20 * 2 + 16));// 28*2
    }

    public String GetCardVlp() throws Exception {
        if (strVst0015.equals(""))
            return "";
        return HexUtil.HexToAsciiString(strVst0015.substring(28 * 2,
                28 * 2 + 24));// 40*2
    }

    public String GetCardUserType() {
        if (strVst0015.equals(""))
            return "";
        return strVst0015.substring(40 * 2, 41 * 2);
    }

    public String GetCardVehicleColor() {
        if (strVst0015.equals(""))
            return "";
        String strResult = "";
        String strCardArea;
        if (nCardVersionType == 1) {
            strResult = vehicleColor("00"
                    + strVst0015.substring(41 * 2, 42 * 2));
        } else {
            strCardArea = HexUtil.HexToAsciiString(strVst0015.substring(0, 8));

            if (strCardArea.equals("云南")) {
                int nCol = (HexUtil.StringToByte(strVst0015.substring(42 * 2,
                        43 * 2)) >>> 4) & 0x0F;
                strResult = vehicleColor(nCol);
            } else if (strCardArea.equals("山东")) {
                // strResult = vehicleColor(strVst0015.substring(41*2, 43*2));
                int nCol = (HexUtil.StringToByte(strVst0015.substring(41 * 2,
                        42 * 2))) & 0xFF;
                strResult = vehicleColor("00" + HexUtil.ByteToString(nCol));
            } else if (strCardArea.equals("浙江") || strCardArea.equals("福建")
                    || strCardArea.equals("安徽") || strCardArea.equals("江苏")
                    || strCardArea.equals("江西")) {
                strResult = vehicleColor(strVst0015.substring(41 * 2, 43 * 2));
            } else {
                strResult = "未定义";
            }
        }
        return strResult;
    }

    public String GetCardBalance() {
        if (strVst0002.equals(""))
            return "";
        long nBalance = Long.parseLong(strVst0002, 16);
        return String.valueOf(nBalance / 100) + "."
                + String.valueOf(nBalance % 100) + "元";
    }

    public String GetVstObuStatus() {
        return strVstObuStatus;
    }

    public String GetObuStatus() {
        String strStatus;
        byte byteStatus = HexUtil.StringToByte(strVstObuStatus.substring(2, 4));
        Log.e("test", "obustatus=" + byteStatus);
        if ((byteStatus & 0x02) == 0x02)
            strStatus = "已拆";
        else
            strStatus = "未拆";

        return strStatus;
    }

    public String GetObuBattery() {
        String strBattery;
        byte byteStatus = HexUtil.StringToByte(strVstObuStatus.substring(2, 4));
        if ((byteStatus & 0x01) == 0x01)
            strBattery = "低电";
        else
            strBattery = "正常";

        return strBattery;
    }

    public String GetObuContractType() {
        return strVstSystemFile.substring(8 * 2, 9 * 2);
    }

    public String GetObuContract() {
        return strVstSystemFile.substring(9 * 2, 10 * 2);
    }

    public String GetObuDate() {
        return strVstSystemFile.substring(18 * 2, 18 * 2 + 16);
    }

    public String GetObuVstSys() {
        return strVstSystemFile;
    }

    /**
     * 把时间拆分加上年月日
     *
     * @param time
     * @return
     */
    public static String convertDate(String time) {
        if (time.equals(""))
            return "";
        String date = null;
        // 年份
        String str = time.substring(0, 4);
        // 月份
        String year = time.substring(4, 6);
        // 日期
        String day = time.substring(6, 8);
        date = str + "年" + year + "月" + day + "日";
        return date;
    }

    /**
     * 解析TransferChannel
     *
     * @param pData
     * @param len
     * @return
     */
    private byte ChannelResolve(byte[] pData, byte len) {
        byte i;
        byte offset = 12;
        byte init = 12;
        // byte[] pOffset = new byte[pData.length];
        byte apduNum, apduLen;
        // System.arraycopy(pData,12,pOffset,0,pData.length-12);

        apduNum = pData[offset];
        offset++;
        strApduList = HexUtil.ByteToString(apduNum);
        for (i = 0; i < apduNum; i++) {
            apduLen = pData[offset];
            offset++;
            strApduList += HexUtil.ByteToString(apduLen);
            strApduList += strTransferChannel.substring(offset * 2,
                    (offset + apduLen) * 2);
            // if(pData[offset+apduLen-2]!=0x90 ||
            // pData[offset+apduLen-1]!=0x00)
            if (!strApduList.substring((offset - init + apduLen - 2) * 2,
                    (offset - init + apduLen - 2) * 2 + 4).equals("9000")) {
                return ERROR_CHANNEL_SW;
            }
            offset += apduLen;
        }
        return 0;
    }

    /**
     * APDU解析
     *
     * @param pData
     * @param len
     * @return
     */
    private byte ApduSwResolve(byte[] pData, byte len) {
        int i;
        int offset = 0;
        int apduNum, apduLen;

        apduNum = (int) pData[offset];
        offset++;
        strApduList = HexUtil.ByteToString(apduNum);
        for (i = 0; i < apduNum; i++) {
            apduLen = (int) pData[offset];
            offset++;
            strApduList += HexUtil.ByteToString(apduLen);
            strApduList += strPsamCmd.substring(offset * 2,
                    (offset + apduLen) * 2);
            // if(pData[offset+apduLen-2]!=0x90 ||
            // pData[offset+apduLen-1]!=0x00)
            if (!strApduList.substring((offset + apduLen - 2) * 2,
                    (offset + apduLen - 2) * 2 + 4).equals("9000")) {
                return ERROR_SW;
            }
            offset += apduLen;
        }
        return 0;
    }

    /**
     * 获取指定APDULISTNUM中的数据
     *
     * @param
     * @return
     */
    public String GetApduListData(int rqApduListNum) {
        int ApduListTotal = Integer.parseInt(strApduList.substring(0, 2), 16);
        int apduLen;
        int offset = 2;
        int i;
        String strResult;
        if (rqApduListNum > ApduListTotal)
            return null;
        for (i = 0; i < ApduListTotal; i++) {
            apduLen = Integer.parseInt(
                    strApduList.substring(offset, offset + 2), 16);
            offset += 2;
            if (rqApduListNum == (i + 1)) {
                strResult = strApduList.substring(offset, offset
                        + (apduLen - 2) * 2);
                return strResult;
            }
            offset += apduLen * 2;

        }

        return null;
    }


    public static void setStrMacId(String strMacId) {
        TcAppFolw.strMacId = strMacId;
    }

    /**
     * @return
     * @throws Exception
     */
    public String SendBst() throws Exception {

        byte[] resultData;
        byte state = 11;
        String strSend = "FFFFFFFF500391C003" + HexUtil.GetRand(3)
                + "53ACE1CD0001418329A01A0004002B00";

        String strResult = manager.SendBst(strSend);
        Log.e("test", "vst=" + strResult);
        timestart = System.currentTimeMillis();
        if (strResult.equals("01")) {

            throw new Exception("搜索OBU失败！");
        } else {

            strVst = strResult.substring(2);
            resultData = HexUtil.decodeHex(strVst.toCharArray());

            if (ResolveDsrcAction(resultData) != R_VST)
                throw new Exception("非VST！");
            if (VstResolve(resultData, (byte) resultData.length) != 0)
                throw new Exception("VST信息错误！");
            // Random random = new Random();
        }
        strMacId = strVst.substring(0, 8);
        strLLC = "77";
        String s = GetOBUSerialNumber();
        Log.e("zzz", "序列号:"+s);
        return strVst;
    }

    public String GetObuVstRandom() {
        return strVstRandom;
    }

    public int GetnObuVersionType() {
        return nObuVersionType;

    }

    public int GetnCardVersionType() {
        return nCardVersionType;

    }

    /**
     * 获取Vst中系统信息(合同序列号)
     *
     * @return
     */
    public String GetOBUSerialNumber() {
        return strVstSystemFile.substring(20, 36);

    }

    public String GetOBUArea() {
        return strVstSystemFile.substring(0, 8);

    }

    public String GetOBUMAC() {
        return strMacId;

    }

    public String GetIC0015() {
        return strVst0015;
    }

    public String GetIC0002() {
        return strVst0002;
    }

    public String GetTransferChanelApduList() {
        return strApduList;
    }

    public String SendGetSecure(int vehicleLen) throws Exception {
        return SendGetSecure2(vehicleLen, "39");
    }

    public String SendGetSecure1(int vehicleLen) throws Exception {
        return SendGetSecure2(vehicleLen, "59");
    }

    public String SendGetSecure2(int vehicleLen, String KeyType)
            throws Exception {
        String strSendCmd = "";
        String strSendCmd2 = "";
        String strVehicle = "";
        String strEnCryData = "";
        String strCryData = "";
        String strAuthCode = "";
        String strRandom = HexUtil.GetRand(8);
        int cryLen = ((1 + vehicleLen + 8) / 8 + 1) * 8;// 8的整数倍数

        String strSend;

        strSend = strMacId + "40" + strLLC + "910501001480010000"
                + HexUtil.ByteToString(vehicleLen) + strRandom + "0000";
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("GetSecure失败！");
        else {
            byte[] resultData;
            strGetSecure = strResult.substring(2);
            resultData = HexUtil.decodeHex(strGetSecure.toCharArray());
            if (ResolveDsrcAction(resultData) != R_GET_RS)
                throw new NumberFormatException("非GetSecureRs！");
            if ((12 + cryLen + 1) > strGetSecure.length() / 2)
                throw new NumberFormatException("GetSecureRs错误！");
        }
        strEnCryData = strGetSecure.substring(12 * 2, (12 + cryLen) * 2);
        if (Constant.Manufacturer==1) {
            try {
                PsamCmd(psamSolt, "00A4000002DF01", null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("选DF01,PSAM" + psamSolt
                        + e.getMessage());
            }

            if (KeyType.equals("59"))
                strSendCmd2 = "801A590310" + GetOBUSerialNumber() + GetOBUArea()
                        + GetOBUArea();
            else
                strSendCmd2 = "801A390308" + GetOBUSerialNumber();
            try {
                PsamCmd(psamSolt, strSendCmd2, null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("密钥分散,PSAM" + psamSolt
                        + e.getMessage());
            }

            strSendCmd = "80FA8000";
            strSendCmd += HexUtil.ByteToString(strEnCryData.length() / 2);
            strSendCmd += strEnCryData;
            Log.i("解密报文", strSendCmd);
            try {
                PsamCmd(psamSolt, strSendCmd, null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("解密,PSAM" + psamSolt
                        + e.getMessage());
            }

            strCryData = GetApduListData(1);
            strAuthCode = strCryData.substring(2, 2 + 16);
            // 解析车辆明文信息
            strVehicle = strCryData.substring(18, 18 + vehicleLen * 2);
            SortVehicle2(strVehicle, vehicleLen * 2);
            // 计算鉴别码分散
            try {
                PsamCmd(psamSolt, strSendCmd2, null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("鉴别码分散,PSAM" + psamSolt
                        + e.getMessage());
            }
            // 计算鉴别码
            strSendCmd = "80FA0800" + HexUtil.ByteToString(vehicleLen + 8)
                    + strRandom + strVehicle;
            try {
                PsamCmd(psamSolt, strSendCmd, null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("鉴别码,PSAM" + psamSolt
                        + e.getMessage());
            }
            String strCalAuthCode = GetApduListData(1);
            Log.i("test", "鉴别码1=" + strCalAuthCode + "\n鉴别码2=" + strAuthCode);
            if (strCalAuthCode.equals(strAuthCode) == false) {
                // TODO：20160803只是返回错误信息，上层无法捕捉异常。
                throw new NumberFormatException("鉴别码错误");
                // return "鉴别码错误";
            }
        }



        return strGetSecure;
    }

    public String SendGetSecure3(int vehicleLen) throws Exception {
        String strRandom = HexUtil.GetRand(8);
        nLenVehiInfo = vehicleLen;
        strGetSecureRand = strRandom;
        int cryLen = ((1 + vehicleLen + 8) / 8 + 1) * 8;// 8的整数倍数
        String strSend = strMacId + "40" + strLLC + "910501001480010000"
                + HexUtil.ByteToString(vehicleLen) + strRandom + "0000";
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";

        String strResult = manager.SendTransparentCom("01", strSend);
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("GetSecure失败！");
        else {
            byte[] resultData;
            strGetSecure = strResult.substring(2);
            resultData = HexUtil.decodeHex(strGetSecure.toCharArray());
            if (ResolveDsrcAction(resultData) != R_GET_RS)
                throw new NumberFormatException("非GetSecureRs！");
            if ((12 + cryLen + 1) > strGetSecure.length() / 2)
                throw new NumberFormatException("GetSecureRs错误！");
        }
        return strGetSecure;
    }
//	public String DeCryptVehiInfo(String KeyType)throws Exception{
//		String strSendCmd = "";
//		String strSendCmd2 = "";
//		String strVehicle = "";
//		String strEnCryData = "";
//		String strCryData = "";
//		String strAuthCode = "";
//		String strRandom = strGetSecureRand;
//		int vehicleLen = nLenVehiInfo;
//		int cryLen = ((1 + vehicleLen + 8) / 8 + 1) * 8;// 8的整数倍数
//
//		strEnCryData = strGetSecure.substring(12 * 2, (12 + cryLen) * 2);
//		int nStep=0;
//		int nIsRun=1;
//		while(nIsRun==1)
//		{
//			switch(nStep)
//			{
//			case 0:
//				if (KeyType.equals("59"))
//					strSendCmd2 = "801A590310" + GetOBUSerialNumber() + GetOBUArea()
//							+ GetOBUArea();
//				else
//					strSendCmd2 = "801A390308" + GetOBUSerialNumber();
//				break;
//			case 1:
//				break;
//			case 2:
//				break;
//			case 3:
//				break;
//			default:
//				nIsRun = 0;
//				break;
//			}
//			try {
//				PsamCmd(psamSolt, strSendCmd2, null, null, null);
//			} catch (Exception e) {
//
//			}
//			nStep++;
//		}
//
//
//
//
//		strSendCmd = "80FA8000";
//		strSendCmd += HexUtil.ByteToString(strEnCryData.length() / 2);
//		strSendCmd += strEnCryData;
//		Log.i("解密报文", strSendCmd);
//		try {
//			PsamCmd(psamSolt, strSendCmd, null, null, null);
//		} catch (Exception e) {
//			String strE = e.getMessage();
//			if (strE.equals("GetSecure失败！"))
//				strE = "读OBU超时，请重试!";
//			else if (strE.equals("非GetSecureRs！"))
//				strE = "读OBU异常数据，请重试!";
//			else if (strE.equals("GetSecureRs错误！"))
//				strE = "读OBU失败,请确认OBU!";
//			else
//				strE = "读OBU失败," + e.getMessage();
//			throw new NumberFormatException(strE);
//			throw new NumberFormatException("解密,PSAM" + psamSolt
//					+ e.getMessage());
//		}
//
//		strCryData = GetApduListData(1);
//		strAuthCode = strCryData.substring(2, 2 + 16);
//		// 解析车辆明文信息
//		strVehicle = strCryData.substring(18, 18 + vehicleLen * 2);
//		SortVehicle2(strVehicle, vehicleLen * 2);
//		// 计算鉴别码分散
//		try {
//			PsamCmd(psamSolt, strSendCmd2, null, null, null);
//		} catch (Exception e) {
//			throw new NumberFormatException("鉴别码分散,PSAM" + psamSolt
//					+ e.getMessage());
//		}
//		// 计算鉴别码
//		strSendCmd = "80FA0800" + HexUtil.ByteToString(vehicleLen + 8)
//				+ strRandom + strVehicle;
//		try {
//			PsamCmd(psamSolt, strSendCmd, null, null, null);
//		} catch (Exception e) {
//			throw new NumberFormatException("鉴别码,PSAM" + psamSolt
//					+ e.getMessage());
//		}
//		String strCalAuthCode = GetApduListData(1);
//		Log.i("test", "鉴别码1=" + strCalAuthCode + "\n鉴别码2=" + strAuthCode);
//		if (strCalAuthCode.equals(strAuthCode) == false) {
//			// TODO：20160803只是返回错误信息，上层无法捕捉异常。
//			throw new NumberFormatException("鉴别码错误");
//			// return "鉴别码错误";
//		}
//	}

    public String SendGetRand() throws Exception {
        String strSend = strMacId + "40" + strLLC + "9104010208";
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("GetRand失败！");
        else {
            byte[] resultData;
            strGetRand = strResult.substring(2);
            resultData = HexUtil.decodeHex(strResult.toCharArray());
            if (ResolveDsrcAction(resultData) != R_GETRAND_RS)
                throw new NumberFormatException("非GetRandRs！");
        }

        return strGetRand;
    }

    /**
     * @param channalID
     * @param pItem1
     * @param pItem2
     * @param pItem3
     * @param pItem4
     * @return
     * @throws Exception
     */
    public String SendTransferChannel(String channalID, String pItem1,
                                      String pItem2, String pItem3, String pItem4) throws Exception {
        int nApduList = 0;
        String strApdu = "";

        if (pItem1 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem1.length() / 2) + pItem1);
        }
        if (pItem2 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem2.length() / 2) + pItem2);
        }
        if (pItem3 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem3.length() / 2) + pItem3);
        }
        if (pItem4 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem4.length() / 2) + pItem4);
        }
        strApdu = (HexUtil.ByteToString(nApduList) + strApdu);

        SendTransferChannel(channalID, strApdu);
        return strTransferChannel;
    }

    /**
     * @param channalID
     * @param apduList
     * @return
     * @throws Exception
     */
    public String SendTransferChannel(String channalID, String apduList)
            throws Exception {
        byte[] resultData;
        String strSend;

        strSend = strMacId + "40" + strLLC + "9105010318" + channalID;
        strSend += apduList;
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("TranferChannel失败！");
        else {
            strTransferChannel = strResult.substring(2);
            resultData = HexUtil.decodeHex(strTransferChannel.toCharArray());
            if (ResolveDsrcAction(resultData) != R_TRANS_RS)
                throw new NumberFormatException("非TransferChannleRs！");
            if (ChannelResolve(resultData, (byte) resultData.length) != 0)
                throw new NumberFormatException("TransferChannleRsSW错误！");
        }

        return strTransferChannel;
    }

    public static String vehicleColor(String color) {
        String colo = "";
        if ("0000".equals(color)) {
            colo = "蓝";
        } else if ("0001".equals(color)) {
            colo = "黄";
        } else if ("0002".equals(color)) {
            colo = "黑";
        } else if ("0003".equals(color)) {
            colo = "白";
        } else {
            colo = "未定义类型0x" + color;
        }
        return colo;
    }

    public static String vehicleColor(int nColo) {
        String colo = "";
        switch (nColo) {
            case 0:
                colo = "蓝";
                break;
            case 1:
                colo = "黄";
                break;
            case 2:
                colo = "黑";
                break;
            case 3:
                colo = "白";
                break;
            default:
                colo = "未定义类型0x" + HexUtil.LongToHexString(nColo, 2, 0);
        }
        return colo;
    }

    public static String GetCardType(String type) {
        String str = "";
        if ("16".equals(type)) {
            str = "储值卡";
        } else if ("17".equals(type)) {
            str = "记账卡";
        } else {
            str = "未定义" + type;
        }
        return str;
    }

    public static String vehicleSize(String size, int type) throws Exception {
        String strSize = "";
        if (type == 1 || type == 0)
            strSize += "长:"
                    + String.valueOf(Integer.parseInt(size.substring(0, 4), 16))
                    + "Dm ";
        if (type == 2 || type == 0) {
            strSize += "宽:"
                    + String.valueOf(Integer.parseInt(size.substring(4, 6), 16))
                    + "Dm ";
            strSize += "高:"
                    + String.valueOf(Integer.parseInt(size.substring(6, 8), 16))
                    + "Dm";
        }
        return strSize;
    }

    public static String vehicleSize2(String size, int type) throws Exception {
        String strSize = "";
        if (type == 1 || type == 0)
            strSize += String
                    .valueOf(Integer.parseInt(size.substring(0, 4), 16));
        if (type == 2 || type == 0) {
            strSize += String
                    .valueOf(Integer.parseInt(size.substring(4, 6), 16)) + "-";
            strSize += String
                    .valueOf(Integer.parseInt(size.substring(6, 8), 16));
        }
        return strSize;
    }

    public void SortVehicle(String strVehicle, int vehicleLen) throws Exception {
        int offset = 0;

        VLP = HexUtil.HexToAsciiString(strVehicle
                .substring(offset, offset + 24));
        offset += 24;
        if (offset >= vehicleLen)
            return;
        VLPC = vehicleColor(strVehicle.substring(offset, offset + 4));
        offset += 4;
        if (offset >= vehicleLen)
            return;
        VClass = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        if (offset >= vehicleLen)
            return;
        VUserType = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        if (offset >= vehicleLen)
            return;
        VSize = vehicleSize2(strVehicle.substring(offset, offset + 8), 1);
        VSize2 = vehicleSize2(strVehicle.substring(offset, offset + 8), 2);
        offset += 8;
        if (offset >= vehicleLen)
            return;
        VWheel = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        if (offset >= vehicleLen)
            return;
        VAxis = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        if (offset >= vehicleLen)
            return;
        VAxisWidth = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 4), 16));
        offset += 4;
        if (offset >= vehicleLen)
            return;
        VWeight =
                String.valueOf(Integer.parseInt(
                        strVehicle.substring(offset, offset + 6), 16));
        offset += 6;
        if (offset >= vehicleLen)
            return;
        VDescribe = HexUtil.HexToAsciiString(strVehicle.substring(offset,
                offset + 32));
        offset += 32;
        if (offset >= vehicleLen)
            return;
        VEngineSN = HexUtil.HexToAsciiString(strVehicle.substring(offset,
                offset + 32));
        offset += 32;

    }


    // ========================================新代码开始================
    int offset = 0;
    // 车辆核定载质量_车轮
    public static String Allowableload_VWheel;
    // 整备质量_车轴数
    public static String curbweight_VAxis;
    // 车辆总质量_车轴距
    public static String totalmass_VAxisWidth;
    // 核定载人数_载重
    public static String numberofpeople_VWeight;
    // 车辆识别号_车辆发动机号
    public static String Vehicle_VEngineSN;


    public String VLP = null;
    public String VLPC = null;
    public String VLPC_1 = null;
    public String VClass = null;
    public String VUserType = null;
    public String VSize = null;
    public String VSize2 = null;
    public String VWheel = null;
    public String VAxis = null;
    public String VAxisWidth = null;
    public String VWeight = null;
    public String VDescribe = null;
    public String VEngineSN = null;

    /**
     * 2019新的车辆解析方式
     *
     * @param strVehicle
     * @param vehicleLen
     * @throws Exception
     */
    public void SortVehicle2(String strVehicle, int vehicleLen)
            throws Exception {
        offset = 0;
        // 车牌号
        VLP = HexUtil.HexToAsciiString(strVehicle
                .substring(offset, offset + 24));
        offset += 24;
        if (offset >= vehicleLen)
            return;
        // 车牌颜色
        VLPC = vehicleColor(strVehicle.substring(offset, offset + 4));
        VLPC_1 = strVehicle.substring(offset, offset + 4);
        offset += 4;
        if (offset >= vehicleLen)
            return;
        // 车型
        VClass = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        String VClass2 = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        if (offset >= vehicleLen)
            return;
        // 客户类型
        VUserType = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        if (offset >= vehicleLen)
            return;
        // 车辆尺寸
        String cheliangchicun = strVehicle.substring(offset, offset + 8);
        VSize = vehicleSize2(cheliangchicun, 1);
        VSize2 = vehicleSize2(cheliangchicun, 2);
        offset += 8;
        if (offset >= vehicleLen)
            return;
        //车轴

        VWheel = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));
        offset += 2;
        if (offset >= vehicleLen)
            return;
        // 车轮
        VAxis = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 2), 16));

        offset += 2;
        if (offset >= vehicleLen)
            return;
        // 轴距
        VAxisWidth = String.valueOf(Integer.parseInt(
                strVehicle.substring(offset, offset + 4), 16));

        offset += 4;


        if (offset >= vehicleLen)
            return;
        // 车辆载重、座位数
        VWeight =
                String.valueOf(Integer.parseInt(
                        strVehicle.substring(offset, offset + 6), 16));


        offset += 6;
        if (offset >= vehicleLen)
            return;

        // 车辆特征描述

        VDescribe = HexUtil.HexToAsciiString(strVehicle.substring(offset,
                offset + 32));
        offset += 32;

        if (offset >= vehicleLen)
            return;
        // 车辆识别代码
        String substring = strVehicle.substring(offset, offset + 34);

        VEngineSN = HexUtil.HexToAsciiString(substring);
        offset += 34;
//			if (offset >= vehicleLen)
//				return;
        // 保留字段
//			String baoliuziduan = strVehicle.substring(130, 144);

//			java.lang.StringIndexOutOfBoundsException: length=126; regionStart=98; regionLength=32

//		}
//		else {
//			Log.e("vlog", "旧的解析");
//			// 用旧的解析
//			offset = 30;
//			// offset += 2;
//			if (offset >= vehicleLen)
//				return;
//			VUserType =  String.valueOf(Integer.parseInt(
//					strVehicle.substring(offset, offset + 2), 16));
//			offset += 2;
//			if (offset >= vehicleLen)
//				return;
//			VSize = vehicleSize2(strVehicle.substring(offset, offset + 8), 1);
//			VSize2 =  vehicleSize2(strVehicle.substring(offset, offset + 8), 2);
//			offset += 8;
//			if (offset >= vehicleLen)
//				return;
//			Allowableload_VWheel =  String.valueOf(Integer.parseInt(
//					strVehicle.substring(offset, offset + 2), 16));
//			offset += 2;
//
//			if (offset >= vehicleLen)
//				return;
//			curbweight_VAxis =  String.valueOf(Integer.parseInt(
//					strVehicle.substring(offset, offset + 2), 16));
//			offset += 2;
//
//
//			if (offset >= vehicleLen)
//				return;
//			totalmass_VAxisWidth = String.valueOf(Integer.parseInt(
//					strVehicle.substring(offset, offset + 4), 16));
//			offset += 4;
//			if (offset >= vehicleLen)
//				return;
//			numberofpeople_VWeight =  String.valueOf(Integer.parseInt(
//					strVehicle.substring(offset, offset + 6), 16));
//			offset += 6;
//			if (offset >= vehicleLen)
//				return;
//			Vehicle_VEngineSN =  HexUtil.HexToAsciiString(strVehicle.substring(offset,
//					offset + 32));
//			offset += 32;
//			if (offset >= vehicleLen)
//				return;
//
//			VDescribe=  HexUtil.HexToAsciiString(strVehicle.substring(offset,
//					offset + 32));
//			offset += 32;
//
//		}

    }

    // =============================================代码结束=========================


    /**
     * 读车辆解密并认证
     *
     * @param vehicleLen
     * @return
     * @throws Exception
     */
    public String SendTransferVehicle(int vehicleLen) throws Exception {
        String strSendCmd = "";
        String strVehicle = "";
        String strEnCryData = "";
        String strCryData = "";
        String strAuthCode = "";
        String strRandom = HexUtil.GetRand(8);

        try {
            SendTransferChannel("02", "00A4000002DF01", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选DF01,ESAM" + e.getMessage());
        }

        strSendCmd = "00B400000A" + strRandom
                + HexUtil.ByteToString(vehicleLen) + "00";// 11223344556677883B00";
        try {
            SendTransferChannel("02", strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("读车辆失败");
        }

        strEnCryData = GetApduListData(1);
        if (strEnCryData == null)
            throw new NumberFormatException("读车辆APDU数据错误");

        try {
            PsamReset(psamSolt);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM" + psamSolt + e.getMessage());
        }

        try {
            PsamCmd(psamSolt, "00A4000002DF01", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选DF01,PSAM" + psamSolt
                    + e.getMessage());
        }

        strSendCmd = "801A390308" + GetOBUSerialNumber();
        try {
            PsamCmd(psamSolt, strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("密钥分散,PSAM" + psamSolt
                    + e.getMessage());
        }

        strSendCmd = "80FA8000";
        strSendCmd += HexUtil.ByteToString(strEnCryData.length() / 2);
        strSendCmd += strEnCryData;
        Log.i("解密报文", strSendCmd);
        try {
            PsamCmd(psamSolt, strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("解密,PSAM" + psamSolt
                    + e.getMessage());
        }

        strCryData = GetApduListData(1);
        strAuthCode = strCryData.substring(2, 2 + 16);
        // 解析车辆明文信息
        strVehicle = strCryData.substring(18, 18 + vehicleLen * 2);
        SortVehicle2(strVehicle, vehicleLen * 2);
        // 计算鉴别码
        strSendCmd = "801A390308" + GetOBUSerialNumber();
        try {
            PsamCmd(psamSolt, strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("鉴别码分散,PSAM" + psamSolt
                    + e.getMessage());
        }
        strSendCmd = "80FA0800" + HexUtil.ByteToString(vehicleLen + 8)
                + strRandom + strVehicle;

        try {
            PsamCmd(psamSolt, strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("鉴别码,PSAM" + psamSolt
                    + e.getMessage());
        }
        String strCalAuthCode = GetApduListData(1);
        Log.i("test", "鉴别码1=" + strCalAuthCode + "\n鉴别码2=" + strAuthCode);
        if (strCalAuthCode.equals(strAuthCode) == false) {
            // TODO：20160803只是返回错误信息，上层无法捕捉异常。
            throw new NumberFormatException("鉴别码错误");
            // return "鉴别码错误";
        }

        return null;
    }

    /**
     * 发送SetMMi
     *
     * @param type ActionParam
     * @return
     * @throws Exception
     */
    public String SendSetMMi(String type) {
        try {
            byte[] resultData;
            String strSend;
            strSend = strMacId + "40" + strLLC + "910501041A" + type;

            String strResult = manager.SendTransparentCom("01", strSend);
            if (strLLC.equals("77"))
                strLLC = "F7";
            else
                strLLC = "77";
            if (strResult.substring(0, 2).equals("00") == false)
                throw new NumberFormatException("SetMMi失败！");
            else {
                strSetMMi = strResult.substring(2);
                resultData = HexUtil.decodeHex(strSetMMi.toCharArray());
                if (ResolveDsrcAction(resultData) != R_SETM_RS)
                    throw new NumberFormatException("非SetMMiRs！");
                return strSetMMi;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 发送EventReport
     *
     * @throws Exception
     */
    public void SendEventReport() throws Exception {
        manager.SendTransparentCom("00", strMacId + "400391600100");
    }


    /**
     * 脱机激活（2）
     *
     * @throws Exception
     */
    public void ObuOfflineActive() throws Exception {
        // UpdateData();
        PsamInit();
        SendBst();
        if (nIsObuOneChip == 1) {
            String strAccess = PsamCalAccessCredentials();
            GetTollData(strAccess, "44", "80", "00004F", null);
            ESAM_WRITEDATA(psamSoltSignChip, 1, "DF01", "46", "41", "01", 26, 1);
        } else {
            if (nCardNoExist == 1) {
                if (strVst0015.equals("")) {
                    throw new NumberFormatException("请插IC卡！");
                }
            }

            String OBUMAC = GetOBUMAC();

            if (OBUMAC.equals(strExminObuMac) == false)
                throw new NumberFormatException("读OBU与预检测的不一致！");
            try {
                if (AreaName.equals("军车")) {
                    SendTransferVehicle(0x4F);
                } else {
                    SendGetSecure2((int) 0x4F, DecryptKeyType);
                }
            } catch (Exception e) {
                String strE = e.getMessage();
                if (strE.equals("GetSecure失败！"))
                    strE = "读OBU超时，请重试!";
                else if (strE.equals("非GetSecureRs！"))
                    strE = "读OBU异常数据，请重试!";
                else if (strE.equals("GetSecureRs错误！"))
                    strE = "读OBU失败,请确认OBU!";
                else
                    strE = "读OBU失败," + e.getMessage();
                throw new NumberFormatException(strE);
            }

            //checkActivateBlackCards(GetCardNetNumber(),GetCardSerialNumber());

            if (nIsCheckEsamIccVersion != 0) {
                if (nObuVersionType != nCardVersionType) {
                    throw new NumberFormatException("OBU版本和IC卡版本不一致！OBU版本："
                            + GetObuContract() + "  IC卡版本：" + GetCardVersion());
                }
            }
//            try {
//                PsamReset(psamSoltWrite);
//                try {
//                    PsamCmd(psamSoltWrite, "00A40000023F00", null, null, null);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            } catch (Exception e) {
//                throw new NumberFormatException("PSAM" + psamSoltWrite
//                        + e.getMessage());
//            }
            String strTmpWriteKeyId = WriteKeyId;
            int nIsSm4 = 0;
            if (GetObuContract().equals("49") || GetObuContract().startsWith("5")) {
                strTmpWriteKeyId = "4" + WriteKeyId.substring(1, 2);
                nIsSm4 = 1;
            }
            ESAM_WRITEDATA(psamSoltWrite, 1, WritePsamDir, WriteKeyType, strTmpWriteKeyId, "01", 26, nIsSm4);
        }
        try {
            SendSetMMi("00");
            SendEventReport();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * OBU脱机检测（1）
     *
     * @throws Exception
     */
    public void ObuOfflineExmin() throws Exception {
        // UpdateData();
        strExminObuMac = "";
        PsamInit();
        SendBst();
        if (nIsObuOneChip == 1) {
            String strAccess = PsamCalAccessCredentials();
            GetTollData(strAccess, "44", "80", "00004F", null);
        } else {
            try {
                if (AreaName.equals("军车")) {
                    SendTransferVehicle(0x4D);
                } else {
                    SendGetSecure2((int) 0x4D, DecryptKeyType);
                }
            } catch (Exception e) {
                String strE = e.getMessage();
                if (strE.equals("GetSecure失败！"))
                    strE = "读OBU超时，请重试!";
                else if (strE.equals("非GetSecureRs！"))
                    strE = "读OBU异常数据，请重试!";
                else if (strE.equals("GetSecureRs错误！"))
                    strE = "读OBU失败,请确认OBU!";
                else
                    strE = "读OBU失败," + e.getMessage();
                throw new NumberFormatException(strE);
            }
        }
        try {
            SendSetMMi("00");
            SendEventReport();
        } catch (Exception e) {
            e.printStackTrace();
        }
        strExminObuMac = GetOBUMAC();
    }

    /**
     * OBU脱机检测
     *
     * @throws Exception
     */
    public void ObuOfflineExminNoPsam() throws Exception {
        // UpdateData();
        strExminObuMac = "";
        SendBst();
        if (nIsObuOneChip == 1) {
            String strAccess = PsamCalAccessCredentials();
            GetTollData(strAccess, "44", "80", "00004F", null);
        }
//		if (nObuVersionType != nCardVersionType) {
//			throw new NumberFormatException("OBU版本和IC卡版本不一致！OBU版本："
//					+ nObuVersionType + "  IC卡版本：" + nCardVersionType);
//		}
        try {
            SendTransferChannel("02", "00A40000023F00", "00B0811B3F", null,
                    null);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM读系统信息," + e.getMessage());
        }

        strEsamSystemFile2 = GetApduListData(2);
        VLP = HexUtil.HexToAsciiString(strEsamSystemFile2.substring(0, 24));
        try {
            SendSetMMi("00");
            SendEventReport();
        } catch (Exception e) {
            e.printStackTrace();
        }
        strExminObuMac = GetOBUMAC();
    }


    public static long timestart;

    /**
     * OBU脱机零消费(3)
     *
     * @param nFlagPsamInit
     * @throws Exception
     */
    public void ObuOfflineConsume(int nFlagPsamInit, String strMacId) throws Exception {

//        if (nFlagPsamInit > 0)
//            PsamInit();

        if (!TextUtils.isEmpty(strMacId)) {
            SendBst(strMacId);
        } else {
            SendBst();
        }

        if (nIsObuOneChip == 1) {
            String strAccess = PsamCalAccessCredentials();
            GetTollData(strAccess, "44", "80", "00004F", null);
            String strRsuRandom = "0102030405060708";
            String strTacPara = "00000000" + "80" + PsamIdNumber + "01020304" + "20200325193000" + "AABBCC";
            SetTollData(strRsuRandom, "41", strTacPara, null);
        } else {
            // 检测OBU是否有卡
            String ICCard = GetCardSerialNumber();
            if (TextUtils.isEmpty(ICCard)) {
                throw new NumberFormatException("用户卡号不存在，请插卡");
            }
            try {
                SendGetSecure2((int) 79, DecryptKeyType);
            } catch (Exception e) {
                String strE = e.getMessage();
                if (strE.equals("GetSecure失败！"))
                    strE = "读OBU超时，请重试!";
                else if (strE.equals("非GetSecureRs！"))
                    strE = "读OBU异常数据，请重试!";
                else if (strE.equals("GetSecureRs错误！"))
                    strE = "读OBU失败,请确认OBU!";
                else
                    strE = "读OBU失败," + e.getMessage();
                throw new NumberFormatException(strE);
            }
            try {
                ConsumeFh();
            } catch (Exception e) {
                e.printStackTrace();
                throw new NumberFormatException("" + e);
            }
        }
        try {
            SendSetMMi("00");
            SendEventReport();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 更新ESAM文件
     *
     * @param isSys   非0表示更新系统信息，0表示更新车辆信息
     * @param PsamDir 目录 例：DF01,DF02,DF03
     * @param KeyType 密钥类型, 例：46,48,26,28
     * @param Data    要更新的数据
     * @param nOffset 数据偏移
     * @throws Exception
     */
    public void ESAM_WRITEDATA(String strPsamSlot, int isSys, String PsamDir, String KeyType,
                               String KeyId, String Data, int nOffset, int nIsSm4) throws Exception {
        String strSendCmd = "";
        String KeyID = "";

        String Value = Data;
        if (SOFT == 1) {
            SoftChipEsamUpdateFile(isSys, Data, nOffset);
            return;
        }
        // 1、ESAM选目录
        if (isSys != 0) {
            KeyID = KeyId;
            strSendCmd = "00A40000023F00";
            // 强行修改分散因子
            if (nOffset < 18)
                Value = GetOBUArea() + Data.substring(8, 20)
                        + GetOBUSerialNumber() + Data.substring(36);
        } else {
            KeyID = HexUtil.ByteToString((HexUtil.StringToByte(KeyId) + 1));
            strSendCmd = "00A4000002DF01";
        }
        try {
            SendTransferChannel("02", strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM选DF01," + e.getMessage());
        }

        String strWrite = "04D681" + HexUtil.ByteToString(nOffset)
                + HexUtil.ByteToString(Data.length() / 2 + 4) + Value;
        // 2、ESAM选中文件及取随机数
        try {
            SendTransferChannel("02", "00A4000002EF01", "0084000004", null,
                    null);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM选EF01取随机数," + e.getMessage());
        }
        String Rand = GetApduListData(2);
        // 3、PSAM选应用目录
        try {
            PsamCmd(strPsamSlot, "00A4000002" + PsamDir, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选" + PsamDir + ",PSAM"
                    + strPsamSlot + e.getMessage());
        }
        // 4、PSAM密钥分散
        if (KeyType.substring(0, 1).equals("4"))
            strSendCmd = "801A" + KeyType + KeyID + "10" + GetOBUSerialNumber()
                    + GetOBUArea() + GetOBUArea();
        else
            strSendCmd = "801A" + KeyType + KeyID + "08" + GetOBUSerialNumber();
        try {
            PsamCmd(strPsamSlot, strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("密钥分散,PSAM" + strPsamSlot
                    + e.getMessage());
        }
        // 5、PSAM计算MAC

        try {
            if (nIsSm4 == 0) {
                strSendCmd = HexUtil.StringApp80(strWrite, 1, 8);
                PsamCmd(strPsamSlot,
                        "80FA0500"
                                + HexUtil.ByteToString(8 + strSendCmd.length() / 2)
                                + Rand + "00000000" + strSendCmd, null, null, null);
            } else {
                strSendCmd = HexUtil.StringApp80(strWrite, 1, 16);
                PsamCmd(strPsamSlot,
                        "80FA0500"
                                + HexUtil.ByteToString(16 + strSendCmd.length() / 2)
                                + Rand + "000000000000000000000000" + strSendCmd, null, null, null);
            }
        } catch (Exception e) {
            throw new NumberFormatException("算MAC,PSAM" + psamSoltWrite
                    + e.getMessage());
        }
        String strMac = GetApduListData(1);
        // 6、ESAM更新文件
        try {
            SendTransferChannel("02", strWrite + strMac, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM更新," + e.getMessage());
        }

    }

    public void SoftChipEsamUpdateFile(int isSys, String Data, int nOffset) throws Exception {
        String strKey;
        String strProcessKey;
        String strFactor = GetOBUSerialNumber() + GetOBUArea() + GetOBUArea();

        String strSendCmd = "";

        String Value = Data;
        // 1、ESAM选目录
        if (isSys != 0) {
            strKey = "11111111111111111111111111111111";
            strSendCmd = "00A40000023F00";
            // 强行修改分散因子
            if (nOffset < 18)
                Value = GetOBUArea() + Data.substring(8, 20)
                        + GetOBUSerialNumber() + Data.substring(36);
        } else {
            strKey = "22222222222222222222222222222222";
            strSendCmd = "00A4000002DF01";
        }
        try {
            SendTransferChannel("02", strSendCmd, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM选DF01," + e.getMessage());
        }

        String strWrite = "04D681" + HexUtil.ByteToString(nOffset)
                + HexUtil.ByteToString(Data.length() / 2 + 4) + Value;
        // 2、ESAM选中文件及取随机数
        try {
            SendTransferChannel("02", "00A4000002EF01", "0084000004", null,
                    null);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM选EF01取随机数," + e.getMessage());
        }
        String Rand = GetApduListData(2);
        // 3、PSAM选应用目录

        // 4、PSAM密钥分散
        strProcessKey = HexUtil.DeliveryKeysSM4(strKey, strFactor);
        // 5、PSAM计算MAC
        strSendCmd = HexUtil.StringApp80(strWrite, 1);
        String strMac;
        try {
            Rand += "000000000000000000000000";
            strMac = HexUtil.GetMacSm4(strProcessKey, Rand, strWrite);
        } catch (Exception e) {
            throw new NumberFormatException("算MAC,PSAM" + psamSoltWrite
                    + e.getMessage());
        }
        // 6、ESAM更新文件
        try {
            SendTransferChannel("02", strWrite + strMac, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("ESAM更新," + e.getMessage());
        }

    }


    public static void UpdateArea(int nAreaNum) {
        psamSolt = "02";
        psamSoltWrite = "02";
        DecryptKeyType = "59";
        WriteKeyType = "26";
        WritePsamDir = "DF03";
        WriteKeyId = "01";

        switch (nAreaNum) {
            case AREA_ITS: // 聚利
                AreaName = "聚利";
                WriteKeyType = "46";
                WritePsamDir = "DF01";
                break;
            case AREA_SX: // 陕西
                AreaName = "陕西";
                break;
            case AREA_AH: // 安徽
                AreaName = "安徽";
                break;
            case AREA_SC: // 江苏
                AreaName = "江苏";
                WritePsamDir = "DF03";
                WriteKeyType = "25";
                psamSolt = "02";
                psamSoltWrite = "02";
                break;
            case AREA_ZJ: // 浙江
                AreaName = "浙江";
                WritePsamDir = "DF01";
                psamSolt = "01";
                psamSoltWrite = "02";
                break;
            case AREA_GZ: // 贵州
                AreaName = "贵州";
                break;
            case AREA_SD: // 山东
                AreaName = "山东";
                break;
            case AREA_HB: // 河北
                AreaName = "河北";
                psamSolt = "02";
                psamSoltWrite = "02";
                break;
            case AREA_YN: // 云南
                AreaName = "云南";
                psamSolt = "01";
                psamSoltWrite = "02";
                break;
            case AREA_FJ: // 福建
                AreaName = "福建";
                WriteKeyType = "28";
                WritePsamDir = "DF02";
                WriteKeyId = "03";
                break;
            case AREA_LL: // 辽宁
                AreaName = "辽宁";
                WritePsamDir = "DF02";
                break;
            case JUNCHE:
                AreaName = "军车";
                WritePsamDir = "DF01";
                WriteKeyType = "28";
                DecryptKeyType = "39";
                break;
            case AREA_TJ:
                AreaName = "天津";
                WritePsamDir = "DF02";
                break;
            case AREA_HN:
                AreaName = "湖南";
                WritePsamDir = "DF01";
                psamSolt = "01";
                psamSoltWrite = "02";
                break;
            case AREA_ZH:
                AreaName = "总后";
                WritePsamDir = "DF01";
                WriteKeyType = "28";
                DecryptKeyType = "39";
                break;
            case AREA_SX2:
                AreaName = "山西";
                WritePsamDir = "DF01";
                WriteKeyType = "28";
                DecryptKeyType = "39";
                break;
            default:
                AreaName = "未知";
                break;
        }

    }

    public static void UpdateArea(String strArea) {
        Log.e("LOG", "设置地区：" + strArea);
        psamSolt = "02";
        psamSoltWrite = "02";
        DecryptKeyType = "59";
        WriteKeyType = "26";
        WritePsamDir = "DF03";
        WriteKeyId = "01";

        if (strArea.equals("聚利")) {
            // 聚利
            AreaName = "聚利";
            WriteKeyType = "46";
            WritePsamDir = "DF01";
        } else if (strArea.equals("陕西")) {
            AreaName = "陕西";
        } else if (strArea.equals("安徽")) {
            AreaName = "安徽";
        } else if (strArea.equals("江苏")) {
            AreaName = "江苏";
            WritePsamDir = "DF03";
            psamSolt = "02";
            psamSoltWrite = "02";
            WriteKeyType = "25";
        } else if (strArea.equals("浙江")) {
            AreaName = "浙江";
            WritePsamDir = "DF01";
            psamSolt = "01";
            psamSoltWrite = "02";
        } else if (strArea.equals("贵州")) {
            AreaName = "贵州";
        } else if (strArea.equals("山东")) {
            AreaName = "山东";
        } else if (strArea.equals("河北")) {
            AreaName = "河北";
            psamSolt = "02";
            psamSoltWrite = "02";
        } else if (strArea.equals("云南")) {
            AreaName = "云南";
            psamSolt = "01";
            psamSoltWrite = "02";
        } else if (strArea.equals("福建")) {
            AreaName = "福建";
            WriteKeyType = "28";
            WritePsamDir = "DF02";
            WriteKeyId = "03";
        } else if (strArea.equals("辽宁")) {
            AreaName = "辽宁";
            WritePsamDir = "DF02";
        } else if (strArea.equals("军车")) {
            AreaName = "军车";
            WritePsamDir = "DF01";
            WriteKeyType = "28";
            DecryptKeyType = "39";
        } else if (strArea.equals("天津")) {
            AreaName = "天津";
            WritePsamDir = "DF02";
        } else if (strArea.equals("湖南")) {
            AreaName = "湖南";
            WritePsamDir = "DF01";
            psamSolt = "01";
            psamSoltWrite = "02";
        } else if (strArea.equals("总后")) {
            AreaName = "总后";
            WritePsamDir = "DF01";
            WriteKeyType = "28";
            DecryptKeyType = "39";
        } else if (strArea.equals("山西")) {
            AreaName = "山西";
            WritePsamDir = "DF01";
            WriteKeyType = "28";
            DecryptKeyType = "39";
        } else {
            AreaName = "未知";
        }

    }

    /**
     * 零消费
     *
     * @throws Exception
     */
    public void ConsumeFh() throws Exception {

        // IC选1001读15文件
        try {
            SendTransferChannel("01", "00A40000021001", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("IC选文件," + e.getMessage());
        }
        try {
            SendTransferChannel("01", null, "00B095002B", null, null);
        } catch (Exception e) {
            throw new NumberFormatException("IC读15," + e.getMessage());
        }
        if (Constant.Manufacturer == 0) {
            try {
                SendTransferChannel("01", null, "00B201CC2B", null, null);
            } catch (Exception e) {
                throw new NumberFormatException("IC读19," + e.getMessage());
            }
        } else {
            try {
                PsamCmd(psamSolt, "00A40000023F00", null, null, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // PSAM取终端机编号
            try {
                PsamCmd(psamSolt, "00B0960006", null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("取终端号,PSAM" + psamSolt
                        + e.getMessage());
            }
            String strTerminalNum = GetApduListData(1);
            // PSAM选DF01目录
            try {
                PsamCmd(psamSolt, "00A4000002DF01", null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("选DF01,PSAM" + psamSolt
                        + e.getMessage());
            }

//        ==================
            // IC消费初始化+写19
            String number = (String) SpfUtils.get(context, "ber_xiaofei", "0");

            float num = Float.parseFloat(number) * 100;
            String strDeNum = HexUtil.LongToHexString((long) num, 4, 0);
            Log.e("testaa", strDeNum);
//		消费金额=========
// 		String strDeNum = "00000000";
            SendTransferChannel(
                    "01",
                    "805003020B" + "01" + strDeNum + strTerminalNum,
                    "80DCAAC82BAA290000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                    null, null);
            String strConIni = GetApduListData(1);
            String strTime = "20140909120101";
            // PSAM算MAC1 11,4
            try {
                PsamCmd(psamSolt,
                        "8070000024" + strConIni.substring(22, 30)
                                + strConIni.substring(8, 12) + strDeNum + "09"
                                + strTime + strConIni.substring(18, 22)
                                + GetCardSerialNumber()
                                + GetIC0015().substring(0, 8)
                                + GetIC0015().substring(0, 8), null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("算MAC1,PSAM" + psamSolt
                        + e.getMessage());
            }
            String strCalMac1 = GetApduListData(1);
            // IC扣款
            try {
                SendTransferChannel("01", "805401000F" + strCalMac1.substring(0, 8)
                        + strTime + strCalMac1.substring(8, 16), null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("IC扣款," + e.getMessage());
            }
        }


        //读19  通用不做  其他
// ================


//        ====================
    }

    public void SetPsamSolt(String psamsolt) {
        psamSolt = psamsolt;
    }

    public String GetPsamSolt() {
        return psamSolt;
    }

    public void SetPsamSoltWrite(String psamsolt) {
        psamSoltWrite = psamsolt;
    }

    public String GetPsamSoltWrite() {
        return psamSoltWrite;
    }

    public String PsamReset(String strPsamSlot) throws Exception {

        String strResult = manager.SendCheckCard(strPsamSlot);
        // byte[] resultData;
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("卡片复位失败！");
        else {
            strPsamRst = strResult.substring(2);
            // resultData = HexUtil.decodeHex(strPsamRst.toCharArray());
            // if(ChannelResolve(resultData,(byte)resultData.length)!=0)
            // throw new NumberFormatException("TransferChannleRsSW错误！");
        }
        return strPsamRst;
    }

    public String PsamCmd(String strPsamSlot, String pItem1, String pItem2,
                          String pItem3, String pItem4) throws Exception {

        int nApduList = 0;
        String strApdu = "";

        if (pItem1 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem1.length() / 2) + pItem1);
        }
//        Log.e("zz1", "pItem1:"+strApdu);
        if (pItem2 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem2.length() / 2) + pItem2);
        }
//        Log.e("zz1", "pItem2:"+strApdu);
        if (pItem3 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem3.length() / 2) + pItem3);
        }
//        Log.e("zz1", "pItem3:"+strApdu);
        if (pItem4 != null) {
            nApduList++;
            strApdu += (HexUtil.ByteToString(pItem4.length() / 2) + pItem4);
        }
//        Log.e("zz1", "pItem4:"+strApdu);
        strApdu = (HexUtil.ByteToString(nApduList) + strApdu);
//        Log.e("zz1", "strApdu:"+strApdu);
        PsamCmd(strPsamSlot, strApdu);
        return strPsamCmd;

    }

    public String PsamCmd(String strPsamSlot, String strCmd) throws Exception {

        String strResult = manager.SendCardCommand(strPsamSlot, strCmd);
//        Log.e("Test", "Psam回应"+strResult);
        byte[] resultData;
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("卡片通道指令失败！");
        else {
            strPsamCmd = strResult.substring(2);
            resultData = HexUtil.decodeHex(strPsamCmd.toCharArray());
            if (ApduSwResolve(resultData, (byte) resultData.length) != 0)
                throw new NumberFormatException("卡片SW错误！");
        }
        return strPsamCmd;
    }

    /**
     * 读取OBU芯片版本 channelID:00
     *
     * @return
     * @throws Exception
     */
    public String SendReadChipVersion() throws Exception {
        byte[] resultData;
        String strSend;

        strSend = strMacId + "40" + strLLC + "9905010318" + "00" + "01010B";
        String strResult = manager.SendTransparentCom("01", strSend);
        Log.e("test", "result=" + strResult);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("TranferChannel失败！");
        else {
            strTransferChannel = strResult.substring(2);
            resultData = HexUtil.decodeHex(strTransferChannel.toCharArray());
            if (ResolveDsrcAction(resultData) != R_TRANS_RS)
                throw new NumberFormatException("非TransferChannleRs！");
            if (ChannelResolve(resultData, (byte) resultData.length, "00") != 0)
                throw new NumberFormatException("TransferChannleRsSW错误！");
        }

        return strTransferChannel;
    }

    public String SendSetSensitivity(String channelID, String prim)
            throws Exception {
        byte[] resultData;
        String strSend;

        strSend = strMacId + "40" + strLLC + "9905010318" + channelID + prim;
        String strResult = manager.SendTransparentCom("01", strSend);
        Log.e("test", "result=" + strResult);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("TranferChannel失败！");
        else {
            strTransferChannel = strResult.substring(2);
            resultData = HexUtil.decodeHex(strTransferChannel.toCharArray());
            if (ResolveDsrcAction(resultData) != R_TRANS_RS)
                throw new NumberFormatException("非TransferChannleRs！");
            if (ChannelResolve(resultData, (byte) resultData.length, "00") != 0)
                throw new NumberFormatException("TransferChannleRsSW错误！");
        }

        return strTransferChannel;
    }

    private byte ChannelResolve(byte[] pData, byte len, String strSW) {
        byte i;
        byte offset = 12;
        byte init = 12;
        // byte[] pOffset = new byte[pData.length];
        byte apduNum, apduLen;
        // System.arraycopy(pData,12,pOffset,0,pData.length-12);

        apduNum = pData[offset];
        offset++;
        strApduList = HexUtil.ByteToString(apduNum);
        for (i = 0; i < apduNum; i++) {
            apduLen = pData[offset];
            offset++;
            strApduList += HexUtil.ByteToString(apduLen);
            strApduList += strTransferChannel.substring(offset * 2,
                    (offset + apduLen) * 2);
            offset += apduLen;
            if (pData[offset] != 0) {
                return ERROR_CHANNEL_SW;
            }
            offset++;
        }
        return 0;
    }


    /**
     * 手机唤醒值通道
     *
     * @param channalID
     * @param apduList
     * @return
     * @throws Exception
     */
    public String SendawakenTransferChannel(String channalID, String apduList)
            throws Exception {
        byte[] resultData;
        String strSend;

        strSend = strMacId + "40" + strLLC + "99050103180001" + channalID;
        strSend += apduList;
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("TranferChannel失败！");
        else {

            strTransferChannel = strResult.substring(2);
//			resultData = HexUtil.decodeHex(strTransferChannel.toCharArray());
//			if (ResolveDsrcAction(resultData) != R_TRANS_RS)
//				throw new NumberFormatException("非TransferChannleRs！");
//			if (ChannelResolve(resultData, (byte) resultData.length) != 0)
//				throw new NumberFormatException("TransferChannleRsSW错误！");
        }
        Log.e("TcAppFolw", "SendawakenTransferChannel strTransferChannel = " + strTransferChannel);
        return strTransferChannel;
    }


    public void Read0019() throws Exception {
        try {
            if (nCardVersionType == 1) {
                SendTransferChannel("01", "00B201CC2B", "00B0952B07", "805C000204", null);
                str0019 = GetApduListData(1);
                str0002 = GetApduListData(3);
                str0015 = GetApduListData(2);
            } else {
                SendTransferChannel("01", "00B201CC2B", "805C000204", null, null);
                str0019 = GetApduListData(1);
                str0002 = GetApduListData(2);
                str0015 = "00000000000000";
            }
        } catch (Exception e) {
            throw new NumberFormatException("读0019文件," + e.getMessage());
        }
    }

    public void Read001B() throws Exception {
        try {
            if (nCardIsGx == 1) {
                SendTransferChannel("01", "00B245D81E", null, null, null);
                str001B = GetApduListData(1);
            } else {
                str001B = HexUtil.HexStringMemset(30, 0);
            }
        } catch (Exception e) {
            throw new NumberFormatException("读001B文件," + e.getMessage());
        }
    }

    /*
     * 读取EF04文件
	 */
    public String ReadEF04(int nRecordNum) {
        String tmpStrEF04 = "";
        int nEF04IdLen = nRecordNum * 6 + 9;
        int nEF04Offset = 0;
        int nEF04ReadLen = 0;
        final int SIZE_FRAME = 105;
        final int MAX_RECORD = 62;
        String strCmd = "";
        nFlagErrorEF04 = 0;
        if (nRecordNum > MAX_RECORD || nRecordNum == 0) {
            nFlagErrorEF04 = 1;
        }
        while ((nEF04Offset <= nEF04IdLen) && (nFlagErrorEF04 == 0)) {
            if ((nEF04IdLen - nEF04Offset) >= SIZE_FRAME)
                nEF04ReadLen = SIZE_FRAME;
            else
                nEF04ReadLen = (nEF04IdLen - nEF04Offset);
            strCmd = "00B084" + HexUtil.ByteToString(nEF04Offset) + HexUtil.ByteToString(nEF04ReadLen);
            try {
                SendTransferChannel("02", strCmd, null, null, null);
            } catch (Exception e) {
                nFlagErrorEF04 = 1;
                break;
            }
            tmpStrEF04 += GetApduListData(1);
            nEF04Offset += SIZE_FRAME;
        }
        if (nFlagErrorEF04 == 1) {
            if (nRecordNum != 0)
                tmpStrEF04 = HexUtil.HexStringMemset(nEF04IdLen, 0xFF);
        }

        return tmpStrEF04;

    }

    public String GxGetSecure(int vehicleLen, String KeyType)
            throws Exception {
        String strSendCmd = "";
        String strSendCmd2 = "";
        String strVehicle = "";
        String strEnCryData = "";
        String strCryData = "";
        String strAuthCode = "";

        strEsamVehicleFile = "";
        String strRandom = HexUtil.GetRand(8);
        int cryLen = ((1 + vehicleLen + 8) / 8 + 1) * 8;// 8的整数倍数

        String strSend;

        strSend = strMacId + "40" + strLLC + "910501001480010000"
                + HexUtil.ByteToString(vehicleLen) + strRandom + "0000";
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("GetSecure失败！");
        else {
            byte[] resultData;
            strGetSecure = strResult.substring(2);
            resultData = HexUtil.decodeHex(strGetSecure.toCharArray());
            if (ResolveDsrcAction(resultData) != R_GET_RS)
                throw new NumberFormatException("非GetSecureRs！");
            if ((12 + cryLen + 1) > strGetSecure.length() / 2)
                throw new NumberFormatException("GetSecureRs错误！");
        }
        strEnCryData = strGetSecure.substring(12 * 2, (12 + cryLen) * 2);
        String strCosHead = "";

        if (KeyType.equals("59")) {
            if (nObuAlgId == 4)
                strCosHead = "801A594310";
            else
                strCosHead = "801A590310";
            strSendCmd2 = strCosHead + GetOBUSerialNumber() + GetOBUArea()
                    + GetOBUArea();
        } else {
            if (nObuAlgId == 4)
                strCosHead = "801A394308";
            else
                strCosHead = "801A390308";
            strSendCmd2 = strCosHead + GetOBUSerialNumber();
        }
        try {
            PsamCmd(psamSolt, strSendCmd2, null, null, null);
        } catch (Exception e) {
            String strE = e.getMessage();
            if (strE.equals("卡片通道指令失败！")) {
                throw new NumberFormatException(strE);
            } else {
                throw new NumberFormatException("密钥分散,PSAM" + psamSolt
                        + e.getMessage());
            }
        }

        strSendCmd = "80FA8000";
        strSendCmd += HexUtil.ByteToString(strEnCryData.length() / 2);
        strSendCmd += strEnCryData;
        Log.i("解密报文", strSendCmd);
        try {
            PsamCmd(psamSolt, strSendCmd, null, null, null);
        } catch (Exception e) {
            String strE = e.getMessage();
            if (strE.equals("卡片通道指令失败！")) {
                throw new NumberFormatException(strE);
            } else {
                throw new NumberFormatException("解密,PSAM" + psamSolt
                        + e.getMessage());
            }
        }

        strCryData = GetApduListData(1);
        strAuthCode = strCryData.substring(2, 2 + 16);
        // 解析车辆明文信息
        strVehicle = strCryData.substring(18, 18 + vehicleLen * 2);
        strEsamVehicleFile = strVehicle;
        SortVehicle2(strVehicle, vehicleLen * 2);
        // 计算鉴别码分散
        try {
            PsamCmd(psamSolt, strSendCmd2, null, null, null);
        } catch (Exception e) {
            String strE = e.getMessage();
            if (strE.equals("卡片通道指令失败！")) {
                throw new NumberFormatException(strE);
            } else {
                throw new NumberFormatException("鉴别码分散,PSAM" + psamSolt
                        + e.getMessage());
            }
        }
        // 计算鉴别码
        strSendCmd = "80FA0800" + HexUtil.ByteToString(vehicleLen + 8)
                + strRandom + strVehicle;
        try {
            PsamCmd(psamSolt, strSendCmd, null, null, null);
        } catch (Exception e) {
            String strE = e.getMessage();
            if (strE.equals("卡片通道指令失败！")) {
                throw new NumberFormatException(strE);
            } else {
                throw new NumberFormatException("鉴别码,PSAM" + psamSolt
                        + e.getMessage());
            }
        }
        String strCalAuthCode = GetApduListData(1);
        Log.i("test", "鉴别码1=" + strCalAuthCode + "\n鉴别码2=" + strAuthCode);
        if (strCalAuthCode.equals(strAuthCode) == false) {
            // TODO：20160803只是返回错误信息，上层无法捕捉异常。
            throw new NumberFormatException("鉴别码错误");
            // return "鉴别码错误";
        }

        return strGetSecure;
    }

    /*
     *复合消费
	 */
    public void GxConsumeFh() throws Exception {

        String strTerminalNum = strPsamTerminalNum;
        String strTime = strConsumeTime;
        String strIccAlgId = "01";
        strIccUserSn = "0000";
        strPsamTerminalSn = "00000000";
        strIccTAC = "00000000";
        strIccBalance = "00000000";
        if (nCardAlgId == 4) {
            strIccAlgId = "4" + strPsamKeyIndex.substring(1, 2);
        }
        //消费金额
        String strDeNum = strConsumeAmount;
        //1、 IC消费初始化+写19
        try {
            SendTransferChannel(
                    "01",
                    "805003020B" + strIccAlgId + strDeNum + strTerminalNum,
                    "80DCAAC82BAA2900" + strConsume0019File,
                    null, null);
        } catch (Exception e) {
            throw new NumberFormatException("消费初始化失败");
        }
        String strConIni = GetApduListData(1);
        strIccUserSn = strConIni.substring(8, 12);
        //2、 PSAM算MAC1 11,4
        try {
            PsamCmd(psamSolt,
                    "8070000024" + strConIni.substring(22, 30)
                            + strIccUserSn + strDeNum + "09"
                            + strTime + strConIni.substring(18, 22)
                            + GetCardSerialNumber()
                            + GetIC0015().substring(0, 8)
                            + GetIC0015().substring(0, 8), null, null, null);
        } catch (Exception e) {
            String strE = e.getMessage();
            if (strE.equals("卡片通道指令失败！")) {
                throw new NumberFormatException(strE);
            } else {
                throw new NumberFormatException("算MAC1,PSAM" + psamSolt
                        + e.getMessage());
            }
        }
        String strCalMac1 = GetApduListData(1);
        strPsamTerminalSn = strCalMac1.substring(0, 8);
        //3、 IC扣款
        try {
            SendTransferChannel("01", "805401000F" + strPsamTerminalSn
                    + strTime + strCalMac1.substring(8, 16), "805C000204", null, null);
        } catch (Exception e) {
            throw new NumberFormatException("IC扣款," + e.getMessage());
        }
        String strConResult = GetApduListData(1);
        strIccTAC = strConResult.substring(0, 8);
        strIccBalance = GetApduListData(2);
        //4、 PSAM验MAC2
        try {
            PsamCmd(psamSolt,
                    "8072000004" + strConResult.substring(8), null, null, null);
        } catch (Exception e) {
            String strE = e.getMessage();
            if (strE.equals("卡片通道指令失败！")) {
                throw new NumberFormatException(strE);
            } else {
                throw new NumberFormatException("验MAC2,PSAM" + psamSolt
                        + e.getMessage());
            }
        }
    }

    /*
     * 交易异常取TAC
	 */
    public void GxExceptionConsumeFh() throws Exception {

        String strTerminalNum = strPsamTerminalNum;
        String strIccAlgId = "01";
        strIccUserSn = "0000";
        strIccTAC = "00000000";
        if (nCardAlgId == 4) {
            strIccAlgId = "4" + strPsamKeyIndex.substring(1, 2);
        }
        //消费金额
        String strDeNum = "00000000";
        //1、 IC消费初始化
        try {
            SendTransferChannel(
                    "01",
                    "805003020B" + strIccAlgId + strDeNum + strTerminalNum,
                    null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("消费初始化失败");
        }
        String strConIni = GetApduListData(1);
        strIccUserSn = strConIni.substring(8, 12);
        //2、 IC取TAC
        try {
            SendTransferChannel(
                    "01",
                    "805A000902" + strIccUserSn,
                    null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("消费初始化失败");
        }
        String strConResult = GetApduListData(1);
        strIccTAC = strConResult.substring(8, 16);
        strIccBalance = str0002;

        long nIccUserSn = HexUtil.HexStringToLong(strIccUserSn);
        nIccUserSn--;
        strIccUserSn = HexUtil.LongToHexString(nIccUserSn, 2, 0);

    }

    public void InitPsam() throws Exception {
        nPsamFlag = 0;
        strPsamTerminalNum = "000000000000";
        // PSAM复位
        try {
            PsamReset(psamSolt);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM" + psamSolt + e.getMessage());
        }
        // PSAM选3F00
        try {
            PsamCmd(psamSolt, "00A40000023F00", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选3F00,PSAM" + psamSolt
                    + e.getMessage());
        }
        // PSAM取终端机编号
        try {
            PsamCmd(psamSolt, "00B0960006", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("取终端号,PSAM" + psamSolt
                    + e.getMessage());
        }
        strPsamTerminalNum = GetApduListData(1);
        //PSAM读0015
        try {
            PsamCmd(psamSolt, "00B095000B", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("读15文件,PSAM" + psamSolt
                    + e.getMessage());
        }
        String strPsam0015 = GetApduListData(1);
        strPsamSerialNo = strPsam0015.substring(0, 20);
        strPsamVersion = strPsam0015.substring(20, 22);
//		int nPsamVersion = Integer.parseInt(strPsamVersion, 16);
//		if(((nPsamVersion&0x0F)>0x05)&&(nPsamVersion!=0xFF))
//		{
//			nPsamFlag = 2;
//		}
//		else
//		{
//			nPsamFlag = 1;
//			strPsamKeyIndex = "01";
//		}
        // PSAM选DF01
        try {
            PsamCmd(psamSolt, "00A4000002DF01", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选DF01,PSAM" + psamSolt
                    + e.getMessage());
        }
        int nPsamVersion = Integer.parseInt(strPsamVersion, 16);
        if (((nPsamVersion & 0x0F) > 0x05) && (nPsamVersion != 0xFF)) {
            //PSAM读0017
            try {
                PsamCmd(psamSolt, "00B0970011", null, null, null);
            } catch (Exception e) {
                throw new NumberFormatException("读15文件,PSAM" + psamSolt
                        + e.getMessage());
            }
            String strPsam0017 = GetApduListData(1);
            strPsamKeyIndex = strPsam0017.substring(0, 2);
            strPsamAreaCode = strPsam0017.substring(9 * 2, (9 + 8) * 2);
            nPsamFlag = 2;
        } else {
            nPsamFlag = 1;
            strPsamKeyIndex = "01";
        }
    }

    public void PsamAuthInit() throws Exception {

        // PSAM选3F00
        try {
            PsamCmd(psamSolt, "00A40000023F00", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选3F00,PSAM" + psamSolt
                    + e.getMessage());
        }
        //PSAM取随机数
        try {
            PsamCmd(psamSolt, "0084000004", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("取随机数,PSAM" + psamSolt
                    + e.getMessage());
        }
        strPsamAuthRandom = GetApduListData(1);
        strPsamAuthRandom += "00000000";
    }

    public void PsamAuth(String strAuthCode) throws Exception {
        // PSAM认证
        try {
            PsamCmd(psamSolt, "0082004108" + strAuthCode, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("外部认证,PSAM" + psamSolt
                    + e.getMessage());
        }
        // PSAM选DF01
        try {
            PsamCmd(psamSolt, "00A4000002DF01", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选DF01,PSAM" + psamSolt
                    + e.getMessage());
        }

    }

    private String strB2 = "";
    private String strB3 = "";
    private String strB4 = "";
    private String strB5 = "";
    private String strBB = "";
    private String strBA = "";
    private String strB0 = "";
    private String strBD = "";//PSAM认证初始化
    private String strBF = "";//PSAM认证

    private String strConsumeAmount = "";//消费金额
    private String strConsumeTime = "";//交易时间
    private String strConsume0019File = "";//要写入的过站信息
    private String strPsamSerialNo = "00010203040506070809";//PSAM卡序列号
    private String strPsamVersion = "00";//PSAM卡版本号
    private String strPsamKeyIndex = "00";//PSAM卡密钥标识
    private String strPsamAreaCode = "B1B1BEA911010001";//PSAM区域代码
    private String strPsamAuthRandom = "0102030405060708";//PSAM卡认证随机数
    private int nPsamFlag = 0;//PSAM卡状态：0表示无PSAM，1表示DES，2表示国密，3表示已授权或无需授权
    private String strPsamTerminalNum = "010203040506";//PSAM终端机编号
    private String strWriteFileTime = "01020304";//C6,C7转换，待完成？？？？？？？？？？？
    private String strIccUserSn = "0000";//IC卡脱机交易序号
    private String strPsamTerminalSn = "00000000";//PSAM卡脱机交易序号
    private String strIccBalance = "00000000";//IC卡交易后余额
    private String strIccTAC = "00000000";//IC卡TAC
    private String strRsuAlgId = "01";//RSU算法标识
    private String strTransType = "09";//交易类型

    private int nFlagErrorEF04 = 0;

    public String GetB2() {
        return strB2;
    }

    public String GetB3() {
        return strB3;
    }

    public String GetB4() {
        return strB4;
    }

    public String GetB5() {
        return strB5;
    }

    public String GetB0() {
        return strB0;
    }

    public String GetBD() {
        return strBD;
    }

    public String GetBF() {
        return strBF;
    }

    /**
     * 广西车道应急收费
     * 返回 0表示成功，小于0表示失败，大于0表示交易结束，还有失败数据
     */
    public int GxObuOfflineConsumeB2() {
        strB2 = "";
        try {
            SendBst();
        } catch (Exception e) {
            return -1;
        }
        strB2 = "B2" + GetOBUMAC() + "00" + GetObuVstSys().substring(0, 16) + GetObuVstSys().substring(20) + GetVstObuStatus() + GetObuVstSys().substring(16, 20);
        return 0;
    }

    /*
     * 返回 0表示成功，小于0表示失败，大于0表示交易结束，还有失败数据
	 */
    public int GxObuOfflineConsumeB3(String strPC) throws Exception {
        int nResult = 0;
        strB3 = "";
        int nErrorCode = 0;
        String strCmd = strPC.substring(0, 2);
        if (strCmd.equals("C1")) {
            try {
                GxGetSecure(79, "59");
            } catch (Exception e) {
                nResult = 1;
                String strE = e.getMessage();
                if (strE.equals("GetSecure失败！"))
                    nErrorCode = 0x38;
                else if (strE.equals("非GetSecureRs！"))
                    nErrorCode = 0x38;
                else if (strE.equals("GetSecureRs错误！"))
                    nErrorCode = 0x38;
                else if (strE.equals("卡片通道指令失败！"))
                    nErrorCode = 0x33;
                else if (strE.equals("鉴别码错误"))
                    nErrorCode = 0x32;
                else
                    nErrorCode = 0x31;
                strB3 = "B3" + GetOBUMAC() + HexUtil.ByteToString(nErrorCode);
                return nResult;
            }
            strB3 = "B3" + GetOBUMAC() + HexUtil.ByteToString(nErrorCode) + GetVehicleInfo();
            return nResult;
        } else if (strCmd.equals("C2")) {
            nResult = -1;
            try {
                SendSetMMi("00");
                SendEventReport();

            } catch (Exception e) {
                e.printStackTrace();
            }

        } else
            nResult = -1;
        return nResult;
    }

    public int GxObuOfflineConsumeB4(String strPC) {
        int nResult = 0;
        strB4 = "";
        int nErrorCode = 0;
        String strCmd = strPC.substring(0, 2);
        if (strCmd.equals("C8")) {
            int nRecordNum = Integer.parseInt(strPC.substring(13 * 2, 14 * 2), 16);
            String strEF04 = ReadEF04(nRecordNum);

            if (nCardNoExist == 1) {
                nResult = 1;
                nErrorCode = 0x47;
                strB4 = "B4" + GetOBUMAC() + HexUtil.ByteToString(nErrorCode);
                return nResult;
            }

            try {
                Read0019();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                nResult = 1;
                nErrorCode = 0x48;
                try {
                    SendSetMMi("00");
                    SendEventReport();
                } catch (Exception e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                //ErrorCode
                strB4 = "B4" + GetOBUMAC() + HexUtil.ByteToString(nErrorCode);
                return nResult;
            }
            try {
                Read001B();
            } catch (Exception e) {
                e.printStackTrace();
                nResult = 1;
                nErrorCode = 0x48;
                try {
                    SendSetMMi("00");
                    SendEventReport();
                } catch (Exception e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                //ErrorCode
                strB4 = "B4" + GetOBUMAC() + HexUtil.ByteToString(nErrorCode);
                return nResult;
            }

            strB4 = "B4" + GetOBUMAC() + "00" + "000009" + str0002 + "00000000" + strVst0015 + str0015 + str0019 + str001B + strEF04;
            nResult = 0;
            return nResult;

        } else if (strCmd.equals("C2")) {
            nResult = -1;
            try {
                SendSetMMi("00");
                SendEventReport();

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else
            nResult = -1;
        return nResult;
    }

    public int GxObuOfflineConsumeB5(String strPC) {
        int nResult = 0;
        strB5 = "";
        int nErrorCode = 0;
        String strCmd = strPC.substring(0, 2);
        int nOffset;
        if (strCmd.equals("C6")) {
            nOffset = 17;
            strConsumeAmount = strPC.substring(nOffset * 2, (nOffset + 4) * 2);
            nOffset += 4;
            strConsumeTime = strPC.substring(nOffset * 2, (nOffset + 7) * 2);
            nOffset += 7;
            strConsume0019File = strPC.substring(nOffset * 2, (nOffset + 40) * 2);
            try {
                GxConsumeFh();
            } catch (Exception e) {
                nResult = 1;
                String strE = e.getMessage();
                if (strE.equals("消费初始化失败"))
                    nErrorCode = 0x51;
                else if (strE.equals("卡片通道指令失败！"))
                    nErrorCode = 0x52;
                else
                    nErrorCode = 0x53;

            }
            strB5 = "B5" + GetOBUMAC() + HexUtil.ByteToString(nErrorCode) + strWriteFileTime + strPsamTerminalNum + strConsumeTime + strTransType + strIccTAC + strIccUserSn + strPsamTerminalSn + strIccBalance + HexUtil.ByteToString(nCardAlgId);
        } else if (strCmd.equals("C7")) {
//			nOffset = 17;
//			strConsumeTime = strPC.substring(nOffset*2, (nOffset+7)*2);
//			nOffset+=7;
//			strConsume0019File = strPC.substring(nOffset*2, (nOffset+40)*2);
            try {
                GxExceptionConsumeFh();
            } catch (Exception e) {
                nResult = 1;
                String strE = e.getMessage();
                if (strE.equals("消费初始化失败"))
                    nErrorCode = 0x51;
                else if (strE.equals("卡片通道指令失败！"))
                    nErrorCode = 0x52;
                else
                    nErrorCode = 0x53;

            }
            strB5 = "B5" + GetOBUMAC() + HexUtil.ByteToString(nErrorCode) + strWriteFileTime + strPsamTerminalNum + strConsumeTime + strTransType + strIccTAC + strIccUserSn + strPsamTerminalSn + strIccBalance + HexUtil.ByteToString(nCardAlgId);

        } else if (strCmd.equals("CB")) {

        } else if (strCmd.equals("C2")) {
            nResult = -1;
            try {
                SendSetMMi("00");
                SendEventReport();

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else
            nResult = -1;
        return nResult;
    }

    public String GxObuOfflineConsumeBB(String strPC) throws Exception {
        return null;
    }

    public String GxObuOfflineConsumeBA(String strPC) throws Exception {
        return null;
    }

    public int GxC0_B0(String strPC) {
        int nResult = 0;
        strB0 = "";
        String strCmd = strPC.substring(0, 2);
        if (strCmd.equals("C0")) {
            try {
                InitPsam();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            int nPsamTotalNum = 0;
            if (nPsamFlag != 0)
                nPsamTotalNum++;
            strB0 = "B000" + HexUtil.ByteToString(nPsamTotalNum) + strPsamTerminalNum + "000000000000" + "00" + "03112233" + "000000" + strPsamVersion + "00";
        } else
            nResult = -1;
        return nResult;
    }

    public int GxCD_BD(String strPC) {
        int nResult = 0;
        strBD = "";
        int nErrorCode = 0;
        String strCmd = strPC.substring(0, 2);
        if (strCmd.equals("CD")) {
            if (nPsamFlag == 3 || nPsamFlag == 2) {
                try {

                    PsamAuthInit();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    nResult = 1;
                    nErrorCode = 2;
                    strBD = "BD" + HexUtil.ByteToString(nErrorCode);
                    return nResult;
                }
            } else {
                nResult = 1;
                nErrorCode = 1;
                strBD = "BD" + HexUtil.ByteToString(nErrorCode);
                return nResult;
            }
            strBD = "BD00" + strPsamSerialNo + strPsamVersion + strPsamAreaCode.substring(0, 8) + strPsamAuthRandom;
        } else
            nResult = -1;
        return nResult;
    }

    public int GxCF_BF(String strPC) {
        int nResult = 0;
        strBF = "";
        int nErrorCode = 0;
        String strCmd = strPC.substring(0, 2);
        if (strCmd.equals("CF")) {
            String strAuthCode = strPC.substring(1 * 2, 9 * 2);
            if (nPsamFlag == 3)
                nPsamFlag = 2;
            try {
                PsamAuth(strAuthCode);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                nResult = 1;
                nErrorCode = 1;
                strBF = "BF" + HexUtil.ByteToString(nErrorCode);
                return nResult;
            }
            nPsamFlag = 3;
            strBF = "BF009000";
        } else
            nResult = -1;
        return nResult;
    }

    public void TestGx() throws Exception {
        int nResult = 0;
        nResult = GxC0_B0("C0");
        if (nResult != 0) {
            throw new NumberFormatException("初始化失败！");
        }
        Log.e("GX", "B0:" + GetB0());
        nResult = GxObuOfflineConsumeB2();
        if (nResult != 0) {
            throw new NumberFormatException("未检测到OBU！");
        }
        Log.e("GX", "B2:" + GetB2());
        nResult = GxObuOfflineConsumeB3("C1112233440102030405060708");
        if (nResult != 0) {
            throw new NumberFormatException("读车辆失败！");
        }
        Log.e("GX", "B3:" + GetB3());
        nResult = GxObuOfflineConsumeB4("C811223344010203040506070800");
        if (nResult != 0) {
            throw new NumberFormatException("读卡片信息失败！");
        }
        Log.e("GX", "B4:" + GetB4());
        nResult = GxObuOfflineConsumeB5("C6112233440102030405060708010203040000000120200102030405" + HexUtil.HexStringMemset(40, 0));
        if (nResult != 0) {
            throw new NumberFormatException("扣款失败！");
        }
        Log.e("GX", "B5:" + GetB5());
        SendSetMMi("00");
        SendEventReport();
        nResult = GxObuOfflineConsumeB2();
        if (nResult != 0) {
            throw new NumberFormatException("未检测到OBU！");
        }
        Log.e("GX", "B2:" + GetB2());
        nResult = GxObuOfflineConsumeB3("C1112233440102030405060708");
        if (nResult != 0) {
            throw new NumberFormatException("读车辆失败！");
        }
        Log.e("GX", "B3:" + GetB3());
        nResult = GxObuOfflineConsumeB4("C811223344010203040506070800");
        if (nResult != 0) {
            throw new NumberFormatException("读卡片信息失败！");
        }
        Log.e("GX", "B4:" + GetB4());
        nResult = GxObuOfflineConsumeB5("C71122334401020304050607080102030420200102030405" + HexUtil.HexStringMemset(40, 0));
        if (nResult != 0) {
            throw new NumberFormatException("取TAC失败！");
        }
        Log.e("GX", "B5:" + GetB5());
        SendSetMMi("00");
        SendEventReport();
    }

    public String GetTollData(String strAccessCredentials, String strKeyIdForAC, String strTransType, String strVehicleInfo, String strTollInfo)
            throws Exception {
        byte[] resultData;
        String strSend;
        int nFilOpt = (int) 0x20;
        if ((strTollInfo != "") && (strTollInfo != null)) nFilOpt = nFilOpt | 0x80;
        strSend = strMacId + "40" + strLLC + "910D010508" + strAccessCredentials + "2A" + HexUtil.ByteToString(nFilOpt) + strTransType + strVehicleInfo;
        if (strTollInfo != null) strSend += strTollInfo;
        strSend += strKeyIdForAC;
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("GetTollData失败！");
        else {
            strGetTollData = strResult.substring(2);
            resultData = HexUtil.decodeHex(strGetTollData.toCharArray());
            if (ResolveDsrcAction(resultData) != R_GETTOLLDATA_RS)
                throw new NumberFormatException("非GetTollDataRs！");
        }
        int nOffset = 11;
        int nGetTollFilOpt = (int) HexUtil.HexStringToLong(strGetTollData.substring(nOffset * 2, (nOffset + 1) * 2));
        nOffset++;
        int nLenVehicle = (int) HexUtil.HexStringToLong(strGetTollData.substring(nOffset * 2, (nOffset + 1) * 2));
        nOffset++;
        strEsamVehicleFile = strGetTollData.substring(nOffset * 2, (nOffset + nLenVehicle) * 2);
        nOffset += nLenVehicle;
        SortVehicle2(strEsamVehicleFile, nLenVehicle * 2);
        if ((nGetTollFilOpt & 0x80) == 0x80)//核对rq中的Opt是否读取过站信息
        {
            int nLenTollInfo = (int) HexUtil.HexStringToLong(strGetTollData.substring(nOffset * 2, (nOffset + 1) * 2));
            nOffset++;
            strGetTollInfo = strGetTollData.substring(nOffset * 2, (nOffset + nLenVehicle) * 2);
            nOffset += nLenTollInfo;
        }
        if ((nGetTollFilOpt & 0x40) == 0x40)//核对rq中的Opt是否读取鉴别码
        {
            strAuthenticator = strGetTollData.substring(nOffset * 2, (nOffset + 8) * 2);
        }
        return strGetTollData;
    }

    public String SetTollData(String strRndRSE, String strKeyIdForAuthen, String strTacPara, String strTollInfo)
            throws Exception {
        byte[] resultData;
        String strSend;
        int nFilOpt = (int) 0x00;
        if ((strTollInfo != "") && (strTollInfo != null)) nFilOpt = nFilOpt | 0x80;
        strSend = strMacId + "40" + strLLC + "91050106" + "2C" + HexUtil.ByteToString(nFilOpt) + strRndRSE + strTacPara;
        if (strTollInfo != null) strSend += strTollInfo;
        strSend += strKeyIdForAuthen;
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("SetTollData失败！");
        else {
            strSetTollData = strResult.substring(2);
            resultData = HexUtil.decodeHex(strSetTollData.toCharArray());
            if (ResolveDsrcAction(resultData) != R_SETTOLLDATA_RS)
                throw new NumberFormatException("非SetTollDataRs！");
        }
        int nOffset = 11;
        strTacInfo = strSetTollData.substring(nOffset * 2, (nOffset + 8) * 2);
        nOffset += 4;
        strAuthenticator = strSetTollData.substring(nOffset * 2, (nOffset + 8) * 2);
        return strSetTollData;
    }

    public int SOFT = 1;

    public void PsamInit() throws Exception {
        if (SOFT == 1) {
            return;
        }
        try {
            PsamReset(psamSoltSignChip);
        } catch (Exception e) {
            throw new NumberFormatException("PSAM" + psamSoltSignChip + e.getMessage());
        }
        try {
            PsamCmd(psamSoltSignChip, "0084000008", null, null, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            PsamCmd(psamSoltSignChip, "00B0960006", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("取终端机编程,PSAM" + psamSoltSignChip
                    + e.getMessage());
        }
        PsamIdNumber = GetApduListData(1);
        try {
            PsamCmd(psamSoltSignChip, "00A4000002DF01", null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("选DF01,PSAM" + psamSoltSignChip
                    + e.getMessage());
        }
    }

    public String SoftCalAccessCredentials() throws Exception {
        String strKey = "66666666666666666666666666666666";
        String strProcessKey;
        String strFactor = GetOBUSerialNumber() + GetOBUArea() + GetOBUArea();
        strProcessKey = HexUtil.DeliveryKeysSM4(strKey, strFactor);
        String strValue = GetObuVstRandom() + "0000000000000000";
        String strAccessCredentials = HexUtil.EnCrypteSm4(strProcessKey, strValue);

        if (strAccessCredentials.length() != 16) {
            byte[] bytsAccess = HexUtil.StringToBytes(strAccessCredentials);
            byte[] bytsResult = new byte[8];
            for (int i = 0; i < 8; i++) {
                bytsResult[i] = (byte) (bytsAccess[i] ^ bytsAccess[8 + i]);
            }
            strAccessCredentials = HexUtil.HexToString(bytsResult);
        }
        return strAccessCredentials;
    }

    public String PsamCalAccessCredentials() throws Exception {
        if (SOFT == 1) {
            return SoftCalAccessCredentials();
        }

        String strSendCmd2 = "801A484A10" + GetOBUSerialNumber() + GetOBUArea()
                + GetOBUArea();
        try {
            PsamCmd(psamSoltSignChip, strSendCmd2, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("密钥分散,PSAM" + psamSoltSignChip
                    + e.getMessage());
        }
        strSendCmd2 = "80FA000010" + GetObuVstRandom() + "0000000000000000";
        try {
            PsamCmd(psamSoltSignChip, strSendCmd2, null, null, null);
        } catch (Exception e) {
            throw new NumberFormatException("计算访问许可,PSAM" + psamSoltSignChip
                    + e.getMessage());
        }
        String strAccessCredentials = GetApduListData(1);
        if (strAccessCredentials.length() != 16) {
            byte[] bytsAccess = HexUtil.StringToBytes(strAccessCredentials);
            byte[] bytsResult = new byte[8];
            for (int i = 0; i < 8; i++) {
                bytsResult[i] = (byte) (bytsAccess[i] ^ bytsAccess[8 + i]);
            }
            strAccessCredentials = HexUtil.HexToString(bytsResult);
        }
        return strAccessCredentials;
    }

    /**
     * 指令00，读取KL15状态 0103A20000
     * 指令02，打开蓝牙 0103A20200
     * 指令03，关闭蓝牙 0103A20300
     * 指令04，读蓝牙MAC+蓝牙名称 0103A20400
     * 指令05，读取车辆VIN码 0103A20500
     * 指令06，写入车辆VIN码 0114A20611FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
     *
     * @param          　 A3
     * @param apduList
     * @return
     * @throws Exception
     */
    public String SendTransferChannelPrivate(String apduList)
            throws Exception {
        byte[] resultData;
        String strSend;
        String strResultData;

        strSend = strMacId + "40" + strLLC + "9105010318" + "A3";
        strSend += apduList;
        String strResult = manager.SendTransparentCom("01", strSend);
        if (strLLC.equals("77"))
            strLLC = "F7";
        else
            strLLC = "77";
        if (strResult.substring(0, 2).equals("00") == false)
            throw new NumberFormatException("TranferChannelPrivate失败！");
        else {
            strTransferChannelPrivate = strResult.substring(2);
            resultData = HexUtil.decodeHex(strTransferChannelPrivate.toCharArray());
            if (resultData[resultData.length - 1] != 0)
                throw new NumberFormatException("TranferChannelPrivate指令失败！");
            if (ResolveDsrcAction(resultData) != R_TRANS_RS)
                throw new NumberFormatException("非TransferChannleRs！");
            strResultData = HexUtil.BytesToString(resultData, 12, resultData.length - 13);
        }

        return strResultData;
    }

    public String SendBst(String strMacIdtmp) throws Exception {

        byte[] resultData;
        byte state = 11;
        String strSend = "FFFFFFFF500391C003" + HexUtil.GetRand(3)
                + "53ACE1CD0001418329A01A0004002B00";

        String strResult = manager.SendBst(strSend);
        Log.e("test", "vst=" + strResult);
        if (strResult.equals("01"))
            throw new Exception("搜索OBU失败！");
        else {
            strVst = strResult.substring(2);
            if (strVst.substring(0, 8).equals(strMacIdtmp) == false)
                throw new Exception("搜索OBU失败！！");
            resultData = HexUtil.decodeHex(strVst.toCharArray());

            if (ResolveDsrcAction(resultData) != R_VST)
                throw new Exception("非VST！");
            if (VstResolve(resultData, (byte) resultData.length) != 0)
                throw new Exception("VST信息错误！");
            // Random random = new Random();
        }

        strMacId = strVst.substring(0, 8);
        strLLC = "77";
        return strVst;
    }

    /**
     * OBU自检 0是失败  1是成功
     *
     * @throws Exception
     */
    public EerrBean check15(String strMacId) {
        EerrBean eerrBean = new EerrBean();
        try {
            String strResult = "";
            //1、OBU检测

            if (!TextUtils.isEmpty(strMacId)) {
                SendBst(strMacId);
            } else {
                SendBst();
            }
        } catch (Exception e) {
            Log.e("test", "" + e);
            eerrBean.setMessage("" + e);
            eerrBean.setCode(0);
            e.printStackTrace();
            return eerrBean;
        }

        try {
            SendTransferChannelPrivate("0103A20000");
            eerrBean.setCode(1);
//                Log.e("test", "自检成功");
        } catch (Exception e) {
            Log.e("test", "自检失败" + e);
            eerrBean.setMessage("" + e);
            eerrBean.setCode(0);
            e.printStackTrace();
        }
        try {
            SendSetMMi("00");
            SendEventReport();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return eerrBean;


    }

    /**
     * 蓝牙检测
     *
     * @param strMacId
     * @return
     */
    public EerrBean Check_Bluetooth(String strMacId) {
        EerrBean eerrBean = new EerrBean();
        try {
            String strResult = "";
            //1、OBU检测

            if (!TextUtils.isEmpty(strMacId)) {
                SendBst(strMacId);
            } else {
                SendBst();
            }
        } catch (Exception e) {
//            Log.e("test", "检测蓝牙BST失败");
            eerrBean.setMessage("" + e);
            eerrBean.setCode(0);
            e.printStackTrace();
            return eerrBean;
        }
        //读取蓝牙名称
        try {
            SendTransferChannelPrivate("0103A20400");
            eerrBean.setCode(1);
        } catch (Exception e) {
            eerrBean.setMessage("" + e);
            eerrBean.setCode(0);
            e.printStackTrace();
        }
        try {
            SendSetMMi("00");
            SendEventReport();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return eerrBean;

    }

    /**
     * OBU交易
     *
     * @param strMacId
     * @return
     */
    public EerrBean Trade(String strMacId) {
        EerrBean eerrBean = new EerrBean();
        try {
            ObuOfflineConsume(0, strMacId);
            eerrBean.setCode(1);
            return eerrBean;
        } catch (Exception e) {
//            Log.e("test", "交易BST失败");
            eerrBean.setMessage("" + e);
            eerrBean.setCode(0);
            return eerrBean;
        }
    }


    public EerrBean Vininput(String strMacId) {
        EerrBean eerrBean = new EerrBean();
        try {

            if (!TextUtils.isEmpty(strMacId)) {
                SendBst(strMacId);
            } else {
                SendBst();
            }
        } catch (Exception e) {
            eerrBean.setMessage("" + e);
            eerrBean.setCode(0);
            return eerrBean;
        }

        try {
            //读取VIN码
//                SendTransferChannelPrivate("0103A20500");
            SendSetMMi("00");
            SendEventReport();
        } catch (Exception e) {
            e.printStackTrace();
            eerrBean.setCode(0);
            eerrBean.setMessage("" + e);
            return eerrBean;
        }
        eerrBean.setCode(1);
        return eerrBean;


    }

}
